FlyBrain-Lab / src /compute /validator.py
timfromhcs's picture
FlyBrain v4.1.0 Space build (REAL_SUBGRAPH, CPU-only, honest backend)
3d46076 verified
Raw
History Blame Contribute Delete
5.73 kB
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)