From 94612a0be0e691d68bcd27a33e529ad30fa3df43 Mon Sep 17 00:00:00 2001 From: hachem Date: Sat, 29 Aug 2026 03:55:18 +0200 Subject: add: complex numbers --- tester/kernels.rs | 420 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 420 insertions(+) create mode 100644 tester/kernels.rs (limited to 'tester/kernels.rs') diff --git a/tester/kernels.rs b/tester/kernels.rs new file mode 100644 index 0000000..b42b181 --- /dev/null +++ b/tester/kernels.rs @@ -0,0 +1,420 @@ +use crate::common::{print_section, states_equal, BenchmarkResult, CircuitCases}; +use psi::{QuantumCircuit, Runtime, RuntimeConfig}; +use std::f64::consts::PI; +use std::time::Instant; + +pub fn run_all(results: &mut Vec) { + println!("═══════════════════════════════════════════════════════════════"); + println!(" KERNEL BATCHING TESTS"); + println!("═══════════════════════════════════════════════════════════════\n"); + + test_kernel_fusion(results); + test_batched_vs_basic(results); + test_batched_large_circuits(results); + test_structure_aware(results); + test_composable_runtime(results); +} + +pub fn test_kernel_fusion(results: &mut Vec) { + print_section("Kernel Fusion Test"); + + let builder = || { + let mut circuit = QuantumCircuit::new(2); + circuit.h(0).t(0).s(0).x(0).h(1).z(1); + circuit + }; + + let circuit = builder(); + let batch = Runtime::build_kernel_batch(2, circuit.operations()); + let original_count = batch.len(); + println!("Original kernels: {}", original_count); + for (i, k) in batch.kernels().iter().enumerate() { + println!(" {}: {} on {:?}", i, k.name, k.targets); + } + + let mut optimized_batch = Runtime::build_kernel_batch(2, circuit.operations()); + optimized_batch.optimize(); + let optimized_count = optimized_batch.len(); + println!("\nOptimized kernels: {}", optimized_count); + for (i, k) in optimized_batch.kernels().iter().enumerate() { + println!(" {}: {} on {:?}", i, k.name, k.targets); + } + + let reduction = ((original_count - optimized_count) as f64 / original_count as f64) * 100.0; + println!( + "\nKernel reduction: {} → {} ({:.0}% fewer)", + original_count, optimized_count, reduction + ); + + let mut basic = builder(); + let start = Instant::now(); + basic.compute_with(Runtime::BasicRT); + let basic_time = start.elapsed(); + + let mut batched = builder(); + let start = Instant::now(); + batched.compute_with(Runtime::BatchedRT); + let batched_time = start.elapsed(); + + let match_result = states_equal(basic.state(), batched.state()); + println!("Results match: {}\n", if match_result { "✓" } else { "✗" }); + + results.push(BenchmarkResult { + name: format!("Fusion ({}→{} kernels)", original_count, optimized_count), + basic_time, + mt_time: batched_time, + results_match: match_result, + }); + + let fusion_heavy = || { + let mut circuit = QuantumCircuit::new(1); + circuit.h(0).t(0).s(0).x(0).y(0).z(0).h(0).t(0); + circuit + }; + + let circuit2 = fusion_heavy(); + let batch2 = Runtime::build_kernel_batch(1, circuit2.operations()); + let orig2 = batch2.len(); + let mut opt_batch2 = Runtime::build_kernel_batch(1, circuit2.operations()); + opt_batch2.optimize(); + let opt2 = opt_batch2.len(); + + let mut basic2 = fusion_heavy(); + let start = Instant::now(); + basic2.compute_with(Runtime::BasicRT); + let basic_time2 = start.elapsed(); + + let mut batched2 = fusion_heavy(); + let start = Instant::now(); + batched2.compute_with(Runtime::BatchedRT); + let batched_time2 = start.elapsed(); + + let match2 = states_equal(basic2.state(), batched2.state()); + + results.push(BenchmarkResult { + name: format!("Heavy fusion ({}→{} kernels)", orig2, opt2), + basic_time: basic_time2, + mt_time: batched_time2, + results_match: match2, + }); +} + +pub fn test_batched_vs_basic(results: &mut Vec) { + print_section("Batched vs Basic Runtime Comparison"); + + let test_cases: CircuitCases = vec![ + ( + "Bell State", + Box::new(|| { + let mut c = QuantumCircuit::new(2); + c.h(0).cnot(0, 1); + c + }), + ), + ( + "GHZ State", + Box::new(|| { + let mut c = QuantumCircuit::new(3); + c.h(0).cnot(0, 1).cnot(0, 2); + c + }), + ), + ( + "Rotation Chain", + Box::new(|| { + let mut c = QuantumCircuit::new(3); + c.rx(0, PI / 4.0) + .ry(0, PI / 4.0) + .rz(0, PI / 4.0) + .rx(1, PI / 3.0) + .ry(1, PI / 3.0); + c + }), + ), + ( + "Mixed Gates", + Box::new(|| { + let mut c = QuantumCircuit::new(4); + c.h(0).h(1).h(2).h(3).cnot(0, 1).cnot(2, 3).cz(1, 2); + c + }), + ), + ]; + + for (name, builder) in test_cases { + let mut basic = builder(); + let start = Instant::now(); + basic.compute_with(Runtime::BasicRT); + let basic_time = start.elapsed(); + + let mut batched = builder(); + let start = Instant::now(); + batched.compute_with(Runtime::BatchedRT); + let batched_time = start.elapsed(); + + let match_result = states_equal(basic.state(), batched.state()); + + println!( + "{}: Basic={:.2}μs, Batched={:.2}μs, Match={}", + name, + basic_time.as_secs_f64() * 1_000_000.0, + batched_time.as_secs_f64() * 1_000_000.0, + if match_result { "✓" } else { "✗" } + ); + + results.push(BenchmarkResult { + name: format!("Batched: {}", name), + basic_time, + mt_time: batched_time, + results_match: match_result, + }); + } + println!(); +} + +pub fn test_batched_large_circuits(results: &mut Vec) { + print_section("Batched Runtime on Large Circuits"); + + let sizes = [8, 10, 12]; + + for &n in &sizes { + let builder = || { + let mut circuit = QuantumCircuit::new(n); + for i in 0..n { + circuit.h(i); + } + for i in 0..(n - 1) { + circuit.cnot(i, i + 1); + } + circuit + }; + + let mut basic_mt = builder(); + let start = Instant::now(); + basic_mt.compute_with(Runtime::BasicRTMT); + let basic_mt_time = start.elapsed(); + + let mut batched_mt = builder(); + let start = Instant::now(); + batched_mt.compute_with(Runtime::BatchedRTMT); + let batched_mt_time = start.elapsed(); + + let match_result = states_equal(basic_mt.state(), batched_mt.state()); + + println!( + "{}-qubit: BasicRTMT={:.3}ms, BatchedRTMT={:.3}ms, Match={}", + n, + basic_mt_time.as_secs_f64() * 1000.0, + batched_mt_time.as_secs_f64() * 1000.0, + if match_result { "✓" } else { "✗" } + ); + + results.push(BenchmarkResult { + name: format!("{}-qubit batched", n), + basic_time: basic_mt_time, + mt_time: batched_mt_time, + results_match: match_result, + }); + } + println!(); +} + +pub fn test_structure_aware(results: &mut Vec) { + print_section("Structure-Aware Kernel Optimisation"); + + let commute_test = || { + let mut c = QuantumCircuit::new(3); + c.t(0).h(1).t(0).h(2).s(0).t(1).rz(0, PI / 4.0); + c + }; + + let circuit = commute_test(); + let mut batch = Runtime::build_structure_aware_batch(3, circuit.operations()); + let original = batch.len(); + println!("Original operations: {}", original); + for (i, k) in batch.kernels().iter().enumerate() { + println!(" {}: {} on {:?} ({:?})", i, k.name, k.targets, k.gate_type); + } + + batch.optimise(); + let optimised = batch.len(); + println!("\nAfter optimisation: {}", optimised); + for (i, k) in batch.kernels().iter().enumerate() { + println!(" {}: {} on {:?}", i, k.name, k.targets); + } + + println!("\nExecution layers: {}", batch.num_layers()); + for (i, layer) in batch.layers().iter().enumerate() { + let names: Vec<_> = layer.kernels.iter().map(|k| k.name.as_str()).collect(); + println!(" Layer {}: {:?}", i, names); + } + + let stats = batch.stats(); + println!("\nStats: {}", stats); + + let mut basic = commute_test(); + let start = Instant::now(); + basic.compute_with(Runtime::BasicRT); + let basic_time = start.elapsed(); + + let mut sa = commute_test(); + let start = Instant::now(); + sa.compute_with(Runtime::StructureAwareRT); + let sa_time = start.elapsed(); + + let match_result = states_equal(basic.state(), sa.state()); + println!( + "\nBasic={:.2}μs, StructureAware={:.2}μs, Match={}", + basic_time.as_secs_f64() * 1_000_000.0, + sa_time.as_secs_f64() * 1_000_000.0, + if match_result { "✓" } else { "✗" } + ); + + results.push(BenchmarkResult { + name: format!("SA: Commuting ({}→{})", original, optimised), + basic_time, + mt_time: sa_time, + results_match: match_result, + }); + + println!(); + print_section("Structure-Aware vs Other Runtimes"); + + let test_cases: CircuitCases = vec![ + ( + "Diagonal-heavy (5q)", + Box::new(|| { + let mut c = QuantumCircuit::new(5); + for q in 0..5 { + c.t(q).s(q).rz(q, PI / 4.0).t(q); + } + c + }), + ), + ( + "Interleaved (4q)", + Box::new(|| { + let mut c = QuantumCircuit::new(4); + c.h(0).h(1).h(2).h(3); + c.t(0).t(1).t(2).t(3); + c.cnot(0, 1).cnot(2, 3); + c.s(0).s(1).s(2).s(3); + c + }), + ), + ( + "Deep rotation (3q)", + Box::new(|| { + let mut c = QuantumCircuit::new(3); + for _ in 0..5 { + for q in 0..3 { + c.rx(q, PI / 8.0).ry(q, PI / 8.0).rz(q, PI / 8.0); + } + } + c + }), + ), + ]; + + for (name, builder) in test_cases { + let mut batched = builder(); + let start = Instant::now(); + batched.compute_with(Runtime::BatchedRT); + let batched_time = start.elapsed(); + + let mut sa = builder(); + let start = Instant::now(); + sa.compute_with(Runtime::StructureAwareRT); + let sa_time = start.elapsed(); + + let match_result = states_equal(batched.state(), sa.state()); + + let speedup = batched_time.as_secs_f64() / sa_time.as_secs_f64(); + println!( + "{}: Batched={:.2}μs, SA={:.2}μs, Speedup={:.2}x, Match={}", + name, + batched_time.as_secs_f64() * 1_000_000.0, + sa_time.as_secs_f64() * 1_000_000.0, + speedup, + if match_result { "✓" } else { "✗" } + ); + + results.push(BenchmarkResult { + name: format!("SA: {}", name), + basic_time: batched_time, + mt_time: sa_time, + results_match: match_result, + }); + } + println!(); +} + +pub fn test_composable_runtime(results: &mut Vec) { + print_section("Composable Runtime Configurations"); + + let builder = || { + let mut c = QuantumCircuit::new(6); + for q in 0..6 { + c.h(q).t(q).s(q); + } + for q in 0..5 { + c.cnot(q, q + 1); + } + for q in 0..6 { + c.rx(q, PI / 4.0).rz(q, PI / 4.0); + } + c + }; + + let configs: Vec<(&str, RuntimeConfig)> = vec![ + ("Basic", RuntimeConfig::new()), + ("Batched", RuntimeConfig::new().batched()), + ("SIMD", RuntimeConfig::new().simd()), + ("Batched+SIMD", RuntimeConfig::new().batched().simd()), + ("SA+SIMD", RuntimeConfig::new().structure_aware().simd()), + ( + "SA+SIMD+Parallel", + RuntimeConfig::new().structure_aware().simd().parallel(), + ), + ("Optimal", Runtime::optimal()), + ]; + + let mut reference = builder(); + reference.compute_with(Runtime::BasicRT); + let ref_state = reference.state().clone(); + + println!("Testing 6-qubit circuit with different runtime configurations:\n"); + + for (name, config) in &configs { + let mut circuit = builder(); + let start = Instant::now(); + circuit.compute_with_config(*config); + let time = start.elapsed(); + + let match_result = states_equal(&ref_state, circuit.state()); + + println!( + "{:20} : {:.2}μs, Match={}", + name, + time.as_secs_f64() * 1_000_000.0, + if match_result { "✓" } else { "✗" } + ); + + results.push(BenchmarkResult { + name: format!("Config: {}", name), + basic_time: time, + mt_time: time, + results_match: match_result, + }); + } + + println!("\nConfiguration Display Examples:"); + println!(" {}", RuntimeConfig::new()); + println!(" {}", RuntimeConfig::new().batched().simd()); + println!( + " {}", + RuntimeConfig::new().structure_aware().simd().parallel() + ); + println!(" {}", Runtime::optimal()); + println!(); +} -- cgit v1.3