#![cfg(test)]
use vyre::DispatchConfig;
use vyre::VyreBackend;
use vyre_driver_cuda::{CudaBackend, CudaBackendRegistration};
use vyre_primitives::predicate::edge_kind;
use weir::fixed_point_resident::{
FixedPointResidentFrontierScratch, FixedPointResidentGraph, FixedPointResidentPlan,
};
use weir::live::{live_closure_borrowed_via, prepare_live_plan};
use weir::oracle::graph::live_closure as live_closure_cpu;
fn run_dispatch(
backend: &CudaBackend,
) -> impl Fn(&vyre::ir::Program, &[&[u8]], Option<[u32; 3]>) -> Result<Vec<Vec<u8>>, String> + '_ {
move |program, inputs, grid_override| {
let mut config = DispatchConfig::default();
config.grid_override = grid_override;
backend
.dispatch_borrowed(program, inputs, &config)
.map_err(|err| err.to_string())
}
}
fn live_dispatcher() -> CudaBackend {
CudaBackend::acquire()
.expect("CudaBackend::acquire failed on a host that must have an NVIDIA GPU.")
}
#[test]
fn cuda_live_chain_propagates_back() {
let backend = live_dispatcher();
let dispatch = run_dispatch(&backend);
let edge_offsets = vec![0u32, 1, 2, 3, 3];
let edge_targets = vec![1u32, 2, 3];
let edge_kind_mask = vec![edge_kind::CONTROL; 3];
let seed_bits = vec![0b1000u32];
let cpu = live_closure_cpu(4, &edge_offsets, &edge_targets, &edge_kind_mask, &seed_bits);
let gpu = live_closure_borrowed_via(
&dispatch,
4,
&edge_offsets,
&edge_targets,
&edge_kind_mask,
&seed_bits,
16,
)
.expect("dispatch");
assert_eq!(gpu, cpu, "chain backward closure divergence");
assert_eq!(gpu, vec![0b1111u32]);
}
#[test]
fn cuda_live_diamond() {
let backend = live_dispatcher();
let dispatch = run_dispatch(&backend);
let edge_offsets = vec![0u32, 2, 3, 4, 4];
let edge_targets = vec![1u32, 2, 3, 3];
let edge_kind_mask = vec![edge_kind::CONTROL; 4];
let seed_bits = vec![0b1000u32];
let cpu = live_closure_cpu(4, &edge_offsets, &edge_targets, &edge_kind_mask, &seed_bits);
let gpu = live_closure_borrowed_via(
&dispatch,
4,
&edge_offsets,
&edge_targets,
&edge_kind_mask,
&seed_bits,
16,
)
.expect("dispatch");
assert_eq!(gpu, cpu);
assert_eq!(gpu, vec![0b1111u32]);
}
#[test]
fn cuda_live_disconnected_pre_succ() {
let backend = live_dispatcher();
let dispatch = run_dispatch(&backend);
let edge_offsets = vec![0u32, 1, 1, 2, 2];
let edge_targets = vec![1u32, 3];
let edge_kind_mask = vec![edge_kind::CONTROL; 2];
let seed_bits = vec![0b0010u32];
let cpu = live_closure_cpu(4, &edge_offsets, &edge_targets, &edge_kind_mask, &seed_bits);
let gpu = live_closure_borrowed_via(
&dispatch,
4,
&edge_offsets,
&edge_targets,
&edge_kind_mask,
&seed_bits,
16,
)
.expect("dispatch");
assert_eq!(gpu, cpu);
assert_eq!(gpu, vec![0b0011u32]);
}
#[test]
fn cuda_live_self_loop_terminates() {
let backend = live_dispatcher();
let dispatch = run_dispatch(&backend);
let edge_offsets = vec![0u32, 1, 1];
let edge_targets = vec![0u32];
let edge_kind_mask = vec![edge_kind::CONTROL];
let seed_bits = vec![0b01u32];
let cpu = live_closure_cpu(2, &edge_offsets, &edge_targets, &edge_kind_mask, &seed_bits);
let gpu = live_closure_borrowed_via(
&dispatch,
2,
&edge_offsets,
&edge_targets,
&edge_kind_mask,
&seed_bits,
50,
)
.expect("dispatch");
assert_eq!(gpu, cpu);
}
#[test]
fn cuda_live_non_control_edge_blocked() {
let backend = live_dispatcher();
let dispatch = run_dispatch(&backend);
let edge_offsets = vec![0u32, 1, 1];
let edge_targets = vec![1u32];
let edge_kind_mask = vec![edge_kind::ASSIGNMENT];
let seed_bits = vec![0b10u32];
let cpu = live_closure_cpu(2, &edge_offsets, &edge_targets, &edge_kind_mask, &seed_bits);
let gpu = live_closure_borrowed_via(
&dispatch,
2,
&edge_offsets,
&edge_targets,
&edge_kind_mask,
&seed_bits,
16,
)
.expect("dispatch");
assert_eq!(gpu, cpu);
assert_eq!(gpu, vec![0b10u32]); }
#[test]
fn cuda_live_resident_graph_parity() {
let backend = CudaBackendRegistration::new(live_dispatcher());
let edge_offsets = vec![0u32, 2, 3, 4, 4];
let edge_targets = vec![1u32, 2, 3, 3];
let edge_kind_mask = vec![edge_kind::CONTROL; 4];
let seed_bits = vec![0b1000u32];
let cpu = live_closure_cpu(4, &edge_offsets, &edge_targets, &edge_kind_mask, &seed_bits);
let plan = prepare_live_plan(4, &edge_offsets, &edge_targets, &edge_kind_mask)
.expect("live plan must prepare for resident CUDA parity");
let config = DispatchConfig::default();
let pipeline = backend
.compile_native(plan.program(), &config)
.expect("CUDA native compile must succeed for resident live parity")
.expect("CUDA backend registration must return a native compiled pipeline for resident live parity");
let resident = FixedPointResidentGraph::upload(&backend, plan.graph())
.expect("CUDA backend must upload live graph as resident resources");
let mut scratch = weir::fixed_point_scratch::FixedPointScratch::default();
let gpu = resident
.live_resident_frontier(&backend, &*pipeline, &seed_bits, 16, &config, &mut scratch)
.expect("resident CUDA live dispatch must converge");
assert_eq!(gpu, cpu);
assert_eq!(gpu, vec![0b1111u32]);
resident
.free(&backend)
.expect("resident live graph resources must free cleanly");
}
#[test]
fn cuda_live_resident_frontier_reuse_parity() {
let backend = CudaBackendRegistration::new(live_dispatcher());
let edge_offsets = vec![0u32, 2, 3, 4, 4];
let edge_targets = vec![1u32, 2, 3, 3];
let edge_kind_mask = vec![edge_kind::CONTROL; 4];
let first_seed = vec![0b1000u32];
let second_seed = vec![0b0010u32];
let first_cpu = live_closure_cpu(
4,
&edge_offsets,
&edge_targets,
&edge_kind_mask,
&first_seed,
);
let second_cpu = live_closure_cpu(
4,
&edge_offsets,
&edge_targets,
&edge_kind_mask,
&second_seed,
);
let plan = prepare_live_plan(4, &edge_offsets, &edge_targets, &edge_kind_mask)
.expect("live plan must prepare for resident CUDA frontier reuse parity");
let config = DispatchConfig::default();
let pipeline = backend
.compile_native(plan.program(), &config)
.expect("CUDA native compile must succeed for resident live frontier reuse parity")
.expect("CUDA backend registration must return a native compiled pipeline for resident live frontier reuse parity");
let resident_plan = FixedPointResidentPlan::new(&backend, plan.graph(), pipeline)
.expect("CUDA backend must upload live resident plan resources");
let mut scratch = weir::fixed_point_scratch::FixedPointScratch::default();
let mut resident_frontier = FixedPointResidentFrontierScratch::default();
let first_gpu = resident_plan
.live_reusing_frontier(
&backend,
&first_seed,
16,
&config,
&mut scratch,
&mut resident_frontier,
)
.expect("first resident CUDA live frontier reuse run must converge");
let second_gpu = resident_plan
.live_reusing_frontier(
&backend,
&second_seed,
16,
&config,
&mut scratch,
&mut resident_frontier,
)
.expect("second resident CUDA live frontier reuse run must converge");
assert!(resident_frontier.is_allocated());
assert_eq!(resident_frontier.byte_len(), 4);
assert_eq!(first_gpu, first_cpu);
assert_eq!(second_gpu, second_cpu);
assert_eq!(first_gpu, vec![0b1111u32]);
assert_eq!(second_gpu, vec![0b0011u32]);
resident_plan
.free_with_frontier(&backend, &mut resident_frontier)
.expect("resident live plan and frontier resources must free cleanly");
}
#[test]
fn cuda_live_resident_sequence_window_uses_final_convergence_readback_only() {
let backend = CudaBackendRegistration::new(live_dispatcher());
let edge_offsets = vec![0u32, 1, 2, 3, 4, 4];
let edge_targets = vec![1u32, 2, 3, 4];
let edge_kind_mask = vec![edge_kind::CONTROL; 4];
let seed_bits = vec![0b10000u32];
let cpu = live_closure_cpu(5, &edge_offsets, &edge_targets, &edge_kind_mask, &seed_bits);
let plan = prepare_live_plan(5, &edge_offsets, &edge_targets, &edge_kind_mask)
.expect("live plan must prepare for sequence-window resident CUDA parity");
let config = DispatchConfig::default();
let pipeline = backend
.compile_native(plan.program(), &config)
.expect("CUDA native compile must succeed for resident live sequence-window parity")
.expect("CUDA backend registration must return a native compiled pipeline for resident live sequence-window parity");
let resident_plan = FixedPointResidentPlan::new(&backend, plan.graph(), pipeline)
.expect("CUDA backend must upload live sequence-window resident plan resources");
let mut scratch = weir::fixed_point_scratch::FixedPointScratch::default();
let mut resident_frontier = FixedPointResidentFrontierScratch::default();
backend.reset_telemetry();
let gpu = resident_plan
.live_reusing_frontier_sequence_window(
&backend,
&plan,
&seed_bits,
16,
&mut scratch,
&mut resident_frontier,
)
.expect("sequence-window resident CUDA live dispatch must converge");
let telemetry = backend.telemetry_snapshot();
assert_eq!(gpu, cpu);
assert_eq!(gpu, vec![0b11111u32]);
assert_eq!(
telemetry.readback_bytes, 8,
"Fix: sequence-window live resident solve must read only final and previous one-word frontiers, not poll every iteration."
);
assert!(
telemetry.sync_points < 16,
"Fix: sequence-window live resident solve must not synchronize once per fixed-point iteration; observed {} sync points.",
telemetry.sync_points
);
assert!(
telemetry.param_upload_bytes < telemetry.kernel_launches.saturating_mul(4),
"Fix: sequence-window live resident solve must hoist repeated fixed-point launch parameter uploads; observed {} parameter bytes across {} launches.",
telemetry.param_upload_bytes,
telemetry.kernel_launches
);
resident_plan
.free_with_frontier(&backend, &mut resident_frontier)
.expect("sequence-window resident live plan and frontier resources must free cleanly");
}