2 Performance Benchmark: SQUANDER vs Qiskit Noisy Circuit Simulation 4 Benchmarks execution time of identical circuits in both frameworks. 6 Run with: python benchmarks/benchmark_perf.py 12 from circuits
import BENCHMARK_CIRCUITS, CIRCUITS_BY_QUBITS
16 PRIMARY_BACKEND =
"density_matrix" 17 REFERENCE_BACKEND =
"qiskit_aer_density_matrix" 25 """Benchmark a function with warmup runs.""" 27 for _
in range(warmup):
32 for _
in range(num_runs):
33 start = time.perf_counter()
35 end = time.perf_counter()
36 times.append((end - start) * 1000)
39 "mean": np.mean(times),
47 """Run benchmark on a list of circuits.""" 50 for name, builder_fn
in circuits:
52 builder = builder_fn()
55 def run_sq(b=builder):
56 rho = DensityMatrix(b.n)
57 b.sq.apply_to(np.array([]), rho)
63 def run_qk(b=builder):
68 speedup = qk_time[
"mean"] / sq_time[
"mean"]
72 "backend": PRIMARY_BACKEND,
73 "reference_backend": REFERENCE_BACKEND,
75 "ops": len(builder.ops),
76 "squander_ms": sq_time[
"mean"],
77 "squander_std": sq_time[
"std"],
78 "qiskit_ms": qk_time[
"mean"],
79 "qiskit_std": qk_time[
"std"],
88 """Print benchmark results in a formatted table.""" 90 f
"\n{'Circuit':<20} {'Qubits':<8} {'Ops':<6} " 91 f
"{'SQUANDER[density_matrix](ms)':<29} " 92 f
"{'Qiskit[qiskit_aer_density_matrix](ms)':<36} {'Speedup':<10}" 98 f
" {r['case_name']:<18} {r['qubits']:<8} {r['ops']:<6} " 99 f
"{r['squander_ms']:>10.3f} {r['qiskit_ms']:>10.3f} {r['speedup']:>6.1f}x" 104 """Print benchmark summary statistics.""" 105 speedups = [r[
"speedup"]
for r
in results]
107 print(
"\n" +
"=" * 70)
108 print(
" BENCHMARK SUMMARY")
111 print(f
"\n Average speedup: {np.mean(speedups):.1f}x faster")
113 best = max(results, key=
lambda x: x[
"speedup"])
114 worst = min(results, key=
lambda x: x[
"speedup"])
117 " Compared backends: {} vs {}".format(
118 PRIMARY_BACKEND, REFERENCE_BACKEND
121 print(f
" Best speedup: {best['speedup']:.1f}x ({best['case_name']})")
122 print(f
" Worst speedup: {worst['speedup']:.1f}x ({worst['case_name']})")
128 " PERFORMANCE BENCHMARK: SQUANDER ({}) vs Qiskit ({})".format(
129 PRIMARY_BACKEND, REFERENCE_BACKEND
133 print(f
"\nMeasuring execution time ({NUM_RUNS} run(s), {WARMUP_RUNS} warmup)...")
136 results =
run_benchmark(BENCHMARK_CIRCUITS, num_runs=NUM_RUNS, warmup=WARMUP_RUNS)
142 print(
"\n" +
"=" * 70)
145 print(
"\n\nDetailed benchmark by qubit count:")
147 for n_qubits
in sorted(CIRCUITS_BY_QUBITS.keys()):
148 circuits = CIRCUITS_BY_QUBITS[n_qubits]
149 print(f
"\n--- {n_qubits}-QUBIT CIRCUITS ---")
150 results =
run_benchmark(circuits, num_runs=NUM_RUNS, warmup=WARMUP_RUNS)
154 f
" {r['case_name']:<20} " 155 f
"SQUANDER[{r['backend']}]: {r['squander_ms']:>8.3f}ms " 156 f
"Qiskit[{r['reference_backend']}]: {r['qiskit_ms']:>10.3f}ms " 157 f
"Speedup: {r['speedup']:>8.1f}x" 160 print(
"\n" +
"=" * 70)
161 print(
" BENCHMARK COMPLETE")
165 if __name__ ==
"__main__":
def print_results(results, title="Benchmark Results")
def print_summary(results)
def run_benchmark(circuits, num_runs=10, warmup=3)
def benchmark_func(func, num_runs=10, warmup=3)