aboutsummaryrefslogtreecommitdiff
path: root/tester
diff options
context:
space:
mode:
authorhachem <im@hachem.wtf>2025-12-10 11:11:53 +0100
committerhachem <im@hachem.wtf>2025-12-10 11:11:53 +0100
commit645846fe8e8ff185f57d5fd70c07c8d8d212bfc3 (patch)
tree86b03099b980c580acf7df2aa28a2e9c79d4672e /tester
parent8066223d25be51627416fb7a05c5234d8c499e55 (diff)
[add]: composable runtime pipeline
Diffstat (limited to 'tester')
-rw-r--r--tester/src/kernels.rs204
1 files changed, 203 insertions, 1 deletions
diff --git a/tester/src/kernels.rs b/tester/src/kernels.rs
index fabe394..5ff7c6d 100644
--- a/tester/src/kernels.rs
+++ b/tester/src/kernels.rs
@@ -1,5 +1,5 @@
use crate::common::{print_section, states_equal, BenchmarkResult};
-use libpsi_core::{QuantumCircuit, Runtime};
+use libpsi_core::{QuantumCircuit, Runtime, RuntimeConfig};
use std::f64::consts::PI;
use std::time::Instant;
@@ -11,6 +11,8 @@ pub fn run_all(results: &mut Vec<BenchmarkResult>) {
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<BenchmarkResult>) {
@@ -216,3 +218,203 @@ pub fn test_batched_large_circuits(results: &mut Vec<BenchmarkResult>) {
}
println!();
}
+
+pub fn test_structure_aware(results: &mut Vec<BenchmarkResult>) {
+ 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: Vec<(&str, Box<dyn Fn() -> QuantumCircuit>)> = 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<BenchmarkResult>) {
+ 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!();
+}