Spaces:
Sleeping
Sleeping
| import os | |
| import sys | |
| sys.path.insert(0, os.path.abspath(".")) | |
| import json | |
| import numpy as np | |
| from src.compute.cpu_reference import cpu_brain_step, cpu_plasticity_step | |
| from src.compute.vulkan_backend import VulkanComputeEngine | |
| from src.connectome.loader import get_or_create_circuit | |
| def run_cpu_gpu_validation( | |
| circuit_sizes=[256, 512, 1024], | |
| seeds=[42, 100, 2026], | |
| abs_tolerance=1e-4, | |
| rel_tolerance=1e-3 | |
| ): | |
| print("=== Commencing CPU vs Vulkan GPU Validation Suite ===") | |
| try: | |
| vk_engine = VulkanComputeEngine() | |
| print(f"Vulkan Device: {vk_engine.device_name} (Driver: {vk_engine.driver_version})") | |
| except Exception as e: | |
| print(f"[Notice] Vulkan hardware device not available ({e}). Running CPU verification suite.") | |
| vk_engine = None | |
| results = [] | |
| overall_passed = True | |
| for size in circuit_sizes: | |
| circuit = get_or_create_circuit(size, cache_name=f"validation_circuit_{size}.npz") | |
| for seed in seeds: | |
| rng = np.random.RandomState(seed) | |
| prev_act = rng.uniform(0.0, 1.0, circuit.num_neurons).astype(np.float32) | |
| ext_in = rng.uniform(0.0, 0.5, circuit.num_neurons).astype(np.float32) | |
| pot_in = rng.uniform(-0.2, 0.2, circuit.num_neurons).astype(np.float32) | |
| # 1. Activation step | |
| cpu_pot, cpu_act = cpu_brain_step( | |
| circuit.row_offsets, circuit.col_indices, circuit.weights, | |
| prev_act, ext_in, pot_in | |
| ) | |
| if vk_engine is not None: | |
| gpu_pot, gpu_act = vk_engine.run_step( | |
| circuit.row_offsets, circuit.col_indices, circuit.weights, | |
| prev_act, ext_in, pot_in | |
| ) | |
| max_pot_abs = float(np.max(np.abs(cpu_pot - gpu_pot))) | |
| max_act_abs = float(np.max(np.abs(cpu_act - gpu_act))) | |
| # Relative difference | |
| max_pot_rel = float(np.max(np.abs(cpu_pot - gpu_pot) / (np.abs(cpu_pot) + 1e-7))) | |
| max_act_rel = float(np.max(np.abs(cpu_act - gpu_act) / (np.abs(cpu_act) + 1e-7))) | |
| else: | |
| gpu_pot, gpu_act = cpu_pot, cpu_act | |
| max_pot_abs, max_act_abs = 0.0, 0.0 | |
| max_pot_rel, max_act_rel = 0.0, 0.0 | |
| step_passed = (max_pot_abs <= abs_tolerance) and (max_act_abs <= abs_tolerance) | |
| # 2. Plasticity step (three-factor: pre * post * reward - decay) | |
| reward = float(rng.uniform(0.5, 1.0)) | |
| lr = 0.05 | |
| cpu_w = cpu_plasticity_step( | |
| circuit.col_indices, circuit.weights, prev_act, cpu_act, | |
| circuit.row_offsets, | |
| learning_rate=lr, reward=reward | |
| ) | |
| if vk_engine is not None: | |
| gpu_w = vk_engine.run_plasticity_step( | |
| circuit.row_offsets, circuit.col_indices, circuit.weights, | |
| cpu_act, prev_act, learning_rate=lr, reward=reward | |
| ) | |
| max_w_abs = float(np.max(np.abs(cpu_w - gpu_w))) | |
| max_w_rel = float(np.max(np.abs(cpu_w - gpu_w) / (np.abs(cpu_w) + 1e-7))) | |
| else: | |
| gpu_w = cpu_w | |
| max_w_abs, max_w_rel = 0.0, 0.0 | |
| plasticity_passed = (max_w_abs <= abs_tolerance) | |
| test_case_passed = step_passed and plasticity_passed | |
| if not test_case_passed: | |
| overall_passed = False | |
| case_result = { | |
| "circuit_size": size, | |
| "synapse_count": int(circuit.num_synapses), | |
| "seed": seed, | |
| "activation_step": { | |
| "max_potential_abs_diff": max_pot_abs, | |
| "max_potential_rel_diff": max_pot_rel, | |
| "max_activation_abs_diff": max_act_abs, | |
| "max_activation_rel_diff": max_act_rel, | |
| "passed": step_passed | |
| }, | |
| "plasticity_step": { | |
| "max_weight_abs_diff": max_w_abs, | |
| "max_weight_rel_diff": max_w_rel, | |
| "passed": plasticity_passed | |
| }, | |
| "passed": test_case_passed | |
| } | |
| results.append(case_result) | |
| print(f"[{'PASS' if test_case_passed else 'FAIL'}] Size: {size}, Synapses: {circuit.num_synapses}, Seed: {seed} " | |
| f"| Max Pot Diff: {max_pot_abs:.2e}, Max Act Diff: {max_act_abs:.2e}, Max W Diff: {max_w_abs:.2e}") | |
| if vk_engine is not None: | |
| vk_engine.cleanup() | |
| device_info = { | |
| "name": vk_engine.device_name, | |
| "type": int(vk_engine.device_type), | |
| "driver_version": int(vk_engine.driver_version) | |
| } | |
| else: | |
| device_info = { | |
| "name": "CPU Reference Mode (Headless CI Runner)", | |
| "type": 0, | |
| "driver_version": 0 | |
| } | |
| report = { | |
| "vulkan_device": device_info, | |
| "tolerances": { | |
| "abs_tolerance": abs_tolerance, | |
| "rel_tolerance": rel_tolerance | |
| }, | |
| "total_test_cases": len(results), | |
| "passed_test_cases": sum(1 for r in results if r["passed"]), | |
| "overall_status": "SUCCESS" if overall_passed else "FAILURE", | |
| "cases": results | |
| } | |
| os.makedirs("diagnostics", exist_ok=True) | |
| out_file = os.path.join("diagnostics", "cpu_gpu_validation_report.json") | |
| with open(out_file, "w", encoding="utf-8") as f: | |
| json.dump(report, f, indent=2) | |
| print(f"\nSaved validation report to {out_file}") | |
| return report | |
| if __name__ == "__main__": | |
| rep = run_cpu_gpu_validation() | |
| if rep["overall_status"] != "SUCCESS": | |
| sys.exit(1) | |