From 5a933df8f2f03290fa82c83991ebecdbb30ab344 Mon Sep 17 00:00:00 2001 From: Omar Elrefaei Date: Sat, 1 Feb 2025 13:13:52 -0500 Subject: [PATCH 1/5] add initial benchmarks --- benchmark/benchmarks.jl | 70 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 benchmark/benchmarks.jl diff --git a/benchmark/benchmarks.jl b/benchmark/benchmarks.jl new file mode 100644 index 0000000..fba09cc --- /dev/null +++ b/benchmark/benchmarks.jl @@ -0,0 +1,70 @@ +using QuantumSymbolics +using QuantumOptics +using QuantumClifford +using BenchmarkTools + +const SUITE = BenchmarkGroup() + +SUITE["import_time"] = BenchmarkGroup(["slow"]) +load_command = `julia --quiet --project=./ --eval="using QuantumSymbolics"` +ttfx_command = ` + julia --quiet --project=./ --eval=""" + using QuantumSymbolics; + @ket k1; @op A; + A * commutator(A,X) * k1 |> qexpand + """` +SUITE["import_time"]["using"] = @benchmarkable run(load_command) samples=3 seconds=15 +SUITE["import_time"]["ttfx"] = @benchmarkable run(ttfx_command) samples=3 seconds=15 +#TODO: qsimplify ttfx is very slow + +# Basic symbolic object creation +SUITE["creation"] = BenchmarkGroup(["symbolic"]) +SUITE["creation"]["ket"] = @benchmarkable @ket k +SUITE["creation"]["op"] = @benchmarkable @op A +SUITE["creation"]["super_op"] = @benchmarkable @superop S + +# Basic operations benchmarks +SUITE["operations"] = BenchmarkGroup(["symbolic"]) +@ket k1; @ket k2; @bra b1; @bra b2; @op A; @op B; @op C; + +SUITE["operations"]["scaling"] = BenchmarkGroup() +SUITE["operations"]["scaling"]["ket"] = @benchmarkable 2 * $k1 +SUITE["operations"]["scaling"]["op"] = @benchmarkable 3 * $A + +SUITE["operations"]["addition"] = BenchmarkGroup() +SUITE["operations"]["addition"]["ket"] = @benchmarkable $k1 + $k2 +SUITE["operations"]["addition"]["op"] = @benchmarkable $A + $B + +SUITE["operations"]["multiplication"] = BenchmarkGroup() +SUITE["operations"]["multiplication"]["bra_ket"] = @benchmarkable $b1 * $k1 +SUITE["operations"]["multiplication"]["op_ket"] = @benchmarkable $A * $k1 +SUITE["operations"]["multiplication"]["bra_op"] = @benchmarkable $b1 * $A +SUITE["operations"]["multiplication"]["inner"] = @benchmarkable $b1 * $k1 +SUITE["operations"]["multiplication"]["outer"] = @benchmarkable $k1 * $b1 +SUITE["operations"]["multiplication"]["op"] = @benchmarkable $A * $B +SUITE["operations"]["multiplication"]["many"] = @benchmarkable $k1 * $b2 * $k2 * $b1 * $A * $B + +SUITE["operations"]["tensor"] = BenchmarkGroup() +SUITE["operations"]["tensor"]["ket"] = @benchmarkable $k1 ⊗ $k2 +SUITE["operations"]["tensor"]["op"] = @benchmarkable $A ⊗ $B +SUITE["operations"]["tensor"]["many"] = @benchmarkable $A ⊗ $B ⊗ $C ⊗ $A ⊗ $B ⊗ $C + +# Linear algebra operations +SUITE["linalg"]["creation"] = BenchmarkGroup(["symbolic"]) +SUITE["linalg"]["trace"] = @benchmarkable tr($A) +SUITE["linalg"]["ptrace"] = @benchmarkable ptrace($A ⊗ $B, 1) +SUITE["linalg"]["inverse"] = @benchmarkable inv($A) +SUITE["linalg"]["dagger"] = @benchmarkable dagger($A) +SUITE["linalg"]["conjugate"] = @benchmarkable conj($A) +SUITE["linalg"]["transpose"] = @benchmarkable transpose($A) +SUITE["linalg"]["commutator"] = @benchmarkable commutator($A, $B) +SUITE["linalg"]["anticommutator"] = @benchmarkable anticommutator($A, $B) + +# Simplification benchmarks +SUITE["manipulation"] = BenchmarkGroup() +compact_pauli_expr = (H * (X+Y+Z)) * (H * (Y1+Y2+Z1)) +expanded_pauli_expr = qexpand(compact_pauli_expr) + +SUITE["manipulation"]["expand"] = @benchmarkable qexpand($compact_pauli_expr) +SUITE["manipulation"]["simplify"]["applicable_rules"] = @benchmarkable qsimplify($expanded_pauli_expr, rewriter=qsimplify_pauli) +SUITE["manipulation"]["simplify"]["irrelevant_rules"] = @benchmarkable qsimplify($expanded_pauli_expr, rewriter=qsimplify_fock) From 105b9154565e311ed8b9579a62164a793adbc38f Mon Sep 17 00:00:00 2001 From: Omar Elrefaei Date: Sat, 1 Feb 2025 20:48:47 -0500 Subject: [PATCH 2/5] add expression benchmarks --- benchmark/benchmarks.jl | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/benchmark/benchmarks.jl b/benchmark/benchmarks.jl index fba09cc..68299a6 100644 --- a/benchmark/benchmarks.jl +++ b/benchmark/benchmarks.jl @@ -68,3 +68,20 @@ expanded_pauli_expr = qexpand(compact_pauli_expr) SUITE["manipulation"]["expand"] = @benchmarkable qexpand($compact_pauli_expr) SUITE["manipulation"]["simplify"]["applicable_rules"] = @benchmarkable qsimplify($expanded_pauli_expr, rewriter=qsimplify_pauli) SUITE["manipulation"]["simplify"]["irrelevant_rules"] = @benchmarkable qsimplify($expanded_pauli_expr, rewriter=qsimplify_fock) + +# Expression benchmarks +SUITE["express"] = BenchmarkGroup(["express"]) +clear_cache!(x) = empty!(x.metadata.express_cache) +state_4 = (Z1⊗Z1 + Z2⊗Z2)/√2 +pauli_op_4 = YCX * transpose(Z⊗Y) * YCZ * dagger(Y⊗X) * conj(ZCY) * exp(X ⊗ (2-3im)X) +pauli_state_8 = (conj(XCY⊗Y) + dagger(Z⊗YCX) + transpose(0.5im*Y ⊗ exp(XCY))) * (X1⊗Y1⊗Z1) + +SUITE["express"]["optics"]["state_4"] = @benchmarkable express($state_4) setup=clear_cache!(state_4) +SUITE["express"]["optics"]["pauli_op_4"] = @benchmarkable express($pauli_op_4) setup=clear_cache!(pauli_op_4) +SUITE["express"]["optics"]["pauli_state_8"] = @benchmarkable express($pauli_state_8) setup=clear_cache!(pauli_state_8) + +# TODO: not sure what else to add here +test_op = X⊗Y +SUITE["express"]["clifford"]["operator"] = @benchmarkable express($X, CliffordRepr()) setup=clear_cache!(X) +SUITE["express"]["clifford"]["observable"] = @benchmarkable express($test_op, CliffordRepr(), UseAsObservable()) setup=clear_cache!(test_op) + From 246fd543aa63c0cecdc0311fcfde25d7da26ca08 Mon Sep 17 00:00:00 2001 From: Omar Elrefaei Date: Sat, 1 Feb 2025 22:16:51 -0500 Subject: [PATCH 3/5] fixup express benchmarks to avoid reading from cache --- benchmark/benchmarks.jl | 52 +++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/benchmark/benchmarks.jl b/benchmark/benchmarks.jl index 68299a6..acdbc30 100644 --- a/benchmark/benchmarks.jl +++ b/benchmark/benchmarks.jl @@ -1,32 +1,33 @@ using QuantumSymbolics -using QuantumOptics -using QuantumClifford +import QuantumOpticsBase +import QuantumClifford + using BenchmarkTools const SUITE = BenchmarkGroup() +@ket k1; @ket k2; @bra b1; @bra b2; @op A; @op B; @op C; -SUITE["import_time"] = BenchmarkGroup(["slow"]) +# Time to import and first usage of simple operations +SUITE["latency"] = BenchmarkGroup(["slow"]) load_command = `julia --quiet --project=./ --eval="using QuantumSymbolics"` ttfx_command = ` julia --quiet --project=./ --eval=""" using QuantumSymbolics; @ket k1; @op A; - A * commutator(A,X) * k1 |> qexpand + A * commutator(A,X) * k1 """` -SUITE["import_time"]["using"] = @benchmarkable run(load_command) samples=3 seconds=15 -SUITE["import_time"]["ttfx"] = @benchmarkable run(ttfx_command) samples=3 seconds=15 -#TODO: qsimplify ttfx is very slow +SUITE["latency"]["using"] = @benchmarkable run(load_command) samples=3 seconds=15 +SUITE["latency"]["ttf_operation"] = @benchmarkable run(ttfx_command) samples=3 seconds=15 +SUITE["latency"]["ttf_simplify"] = @benchmarkable qsimplify(X*Y) samples=1 # Basic symbolic object creation SUITE["creation"] = BenchmarkGroup(["symbolic"]) -SUITE["creation"]["ket"] = @benchmarkable @ket k -SUITE["creation"]["op"] = @benchmarkable @op A -SUITE["creation"]["super_op"] = @benchmarkable @superop S +SUITE["creation"]["ket"] = @benchmarkable @ket _k +SUITE["creation"]["op"] = @benchmarkable @op _A +SUITE["creation"]["super_op"] = @benchmarkable @superop _S -# Basic operations benchmarks +# Basic operations SUITE["operations"] = BenchmarkGroup(["symbolic"]) -@ket k1; @ket k2; @bra b1; @bra b2; @op A; @op B; @op C; - SUITE["operations"]["scaling"] = BenchmarkGroup() SUITE["operations"]["scaling"]["ket"] = @benchmarkable 2 * $k1 SUITE["operations"]["scaling"]["op"] = @benchmarkable 3 * $A @@ -50,7 +51,7 @@ SUITE["operations"]["tensor"]["op"] = @benchmarkable $A ⊗ $B SUITE["operations"]["tensor"]["many"] = @benchmarkable $A ⊗ $B ⊗ $C ⊗ $A ⊗ $B ⊗ $C # Linear algebra operations -SUITE["linalg"]["creation"] = BenchmarkGroup(["symbolic"]) +SUITE["linalg"] = BenchmarkGroup(["symbolic"]) SUITE["linalg"]["trace"] = @benchmarkable tr($A) SUITE["linalg"]["ptrace"] = @benchmarkable ptrace($A ⊗ $B, 1) SUITE["linalg"]["inverse"] = @benchmarkable inv($A) @@ -61,27 +62,32 @@ SUITE["linalg"]["commutator"] = @benchmarkable commutator($A, $B) SUITE["linalg"]["anticommutator"] = @benchmarkable anticommutator($A, $B) # Simplification benchmarks -SUITE["manipulation"] = BenchmarkGroup() +SUITE["manipulation"] = BenchmarkGroup(["symbolic"]) compact_pauli_expr = (H * (X+Y+Z)) * (H * (Y1+Y2+Z1)) expanded_pauli_expr = qexpand(compact_pauli_expr) +commutator_expr = commutator(X, commutator(Y, commutator(X, Z))) -SUITE["manipulation"]["expand"] = @benchmarkable qexpand($compact_pauli_expr) +SUITE["manipulation"]["expand"]["distribution"] = @benchmarkable qexpand($compact_pauli_expr) +SUITE["manipulation"]["expand"]["commutator"] = @benchmarkable qexpand($commutator_expr) SUITE["manipulation"]["simplify"]["applicable_rules"] = @benchmarkable qsimplify($expanded_pauli_expr, rewriter=qsimplify_pauli) +# Expression isn't simplified with fock rules. Testing how fast we go through inapplicable rules. SUITE["manipulation"]["simplify"]["irrelevant_rules"] = @benchmarkable qsimplify($expanded_pauli_expr, rewriter=qsimplify_fock) +SUITE["manipulation"]["simplify"]["commutator"] = @benchmarkable qsimplify($commutator_expr, rewriter=qsimplify_commutator) # Expression benchmarks SUITE["express"] = BenchmarkGroup(["express"]) clear_cache!(x) = empty!(x.metadata.express_cache) -state_4 = (Z1⊗Z1 + Z2⊗Z2)/√2 +simple_op = X⊗Y +simple_ket = Z1⊗Z1 pauli_op_4 = YCX * transpose(Z⊗Y) * YCZ * dagger(Y⊗X) * conj(ZCY) * exp(X ⊗ (2-3im)X) pauli_state_8 = (conj(XCY⊗Y) + dagger(Z⊗YCX) + transpose(0.5im*Y ⊗ exp(XCY))) * (X1⊗Y1⊗Z1) -SUITE["express"]["optics"]["state_4"] = @benchmarkable express($state_4) setup=clear_cache!(state_4) -SUITE["express"]["optics"]["pauli_op_4"] = @benchmarkable express($pauli_op_4) setup=clear_cache!(pauli_op_4) -SUITE["express"]["optics"]["pauli_state_8"] = @benchmarkable express($pauli_state_8) setup=clear_cache!(pauli_state_8) +SUITE["express"]["optics"]["simple_op"] = @benchmarkable express($simple_op) setup=clear_cache!(simple_op) evals=1 +SUITE["express"]["optics"]["simple_ket"] = @benchmarkable express($simple_ket) setup=clear_cache!(simple_ket) evals=1 +SUITE["express"]["optics"]["pauli_op_4"] = @benchmarkable express($pauli_op_4) setup=clear_cache!(pauli_op_4) evals=1 +SUITE["express"]["optics"]["pauli_state_8"] = @benchmarkable express($pauli_state_8) setup=clear_cache!(pauli_state_8) evals=1 # TODO: not sure what else to add here -test_op = X⊗Y -SUITE["express"]["clifford"]["operator"] = @benchmarkable express($X, CliffordRepr()) setup=clear_cache!(X) -SUITE["express"]["clifford"]["observable"] = @benchmarkable express($test_op, CliffordRepr(), UseAsObservable()) setup=clear_cache!(test_op) +SUITE["express"]["clifford"]["simple_ket"] = @benchmarkable express($simple_ket, CliffordRepr()) setup=clear_cache!(simple_ket) evals=1 +SUITE["express"]["clifford"]["simple_observable"] = @benchmarkable express($simple_op, CliffordRepr(), UseAsObservable()) setup=clear_cache!(simple_op) evals=1 From 91cc3ae66c41867cc5d6dbdce94b57ae696ad1ba Mon Sep 17 00:00:00 2001 From: Omar Elrefaei Date: Wed, 5 Feb 2025 09:11:07 -0500 Subject: [PATCH 4/5] add benchmarks for large trees --- benchmark/benchmarks.jl | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/benchmark/benchmarks.jl b/benchmark/benchmarks.jl index acdbc30..c916d47 100644 --- a/benchmark/benchmarks.jl +++ b/benchmark/benchmarks.jl @@ -18,14 +18,29 @@ ttfx_command = ` """` SUITE["latency"]["using"] = @benchmarkable run(load_command) samples=3 seconds=15 SUITE["latency"]["ttf_operation"] = @benchmarkable run(ttfx_command) samples=3 seconds=15 -SUITE["latency"]["ttf_simplify"] = @benchmarkable qsimplify(X*Y) samples=1 +SUITE["latency"]["ttf_simplify"] = @benchmarkable qsimplify(X*Y) samples=1 evals=1 -# Basic symbolic object creation + +# Symbolic object creation SUITE["creation"] = BenchmarkGroup(["symbolic"]) SUITE["creation"]["ket"] = @benchmarkable @ket _k SUITE["creation"]["op"] = @benchmarkable @op _A SUITE["creation"]["super_op"] = @benchmarkable @superop _S +SUITE["creation"]["large_trees"] = BenchmarkGroup(["allocs"]) +function large_tree_with_plenty_reallocations(layers) + expr_op = QuantumSymbolics.I + expr_ket = X1 + for _ in 1:layers + expr_op = rand([X, Y, Z, H]) + (rand([X, Y, Z, H]) * expr_op) + expr_ket = (expr_op * expr_ket) + rand([X1, X2, Y1, Y2, Z1, Z2]) + end + return expr_op, expr_ket +end +SUITE["creation"]["large_trees"]["10_layers"] = @benchmarkable large_tree_with_plenty_reallocations(10) +SUITE["creation"]["large_trees"]["50_layers"] = @benchmarkable large_tree_with_plenty_reallocations(50) + + # Basic operations SUITE["operations"] = BenchmarkGroup(["symbolic"]) SUITE["operations"]["scaling"] = BenchmarkGroup() @@ -50,6 +65,7 @@ SUITE["operations"]["tensor"]["ket"] = @benchmarkable $k1 ⊗ $k2 SUITE["operations"]["tensor"]["op"] = @benchmarkable $A ⊗ $B SUITE["operations"]["tensor"]["many"] = @benchmarkable $A ⊗ $B ⊗ $C ⊗ $A ⊗ $B ⊗ $C + # Linear algebra operations SUITE["linalg"] = BenchmarkGroup(["symbolic"]) SUITE["linalg"]["trace"] = @benchmarkable tr($A) @@ -61,6 +77,7 @@ SUITE["linalg"]["transpose"] = @benchmarkable transpose($A) SUITE["linalg"]["commutator"] = @benchmarkable commutator($A, $B) SUITE["linalg"]["anticommutator"] = @benchmarkable anticommutator($A, $B) + # Simplification benchmarks SUITE["manipulation"] = BenchmarkGroup(["symbolic"]) compact_pauli_expr = (H * (X+Y+Z)) * (H * (Y1+Y2+Z1)) @@ -74,6 +91,7 @@ SUITE["manipulation"]["simplify"]["applicable_rules"] = @benchmarkable qsimplify SUITE["manipulation"]["simplify"]["irrelevant_rules"] = @benchmarkable qsimplify($expanded_pauli_expr, rewriter=qsimplify_fock) SUITE["manipulation"]["simplify"]["commutator"] = @benchmarkable qsimplify($commutator_expr, rewriter=qsimplify_commutator) + # Expression benchmarks SUITE["express"] = BenchmarkGroup(["express"]) clear_cache!(x) = empty!(x.metadata.express_cache) @@ -87,7 +105,7 @@ SUITE["express"]["optics"]["simple_ket"] = @benchmarkable express($simple_ket) s SUITE["express"]["optics"]["pauli_op_4"] = @benchmarkable express($pauli_op_4) setup=clear_cache!(pauli_op_4) evals=1 SUITE["express"]["optics"]["pauli_state_8"] = @benchmarkable express($pauli_state_8) setup=clear_cache!(pauli_state_8) evals=1 -# TODO: not sure what else to add here +# TODO: add additional clifford expressions SUITE["express"]["clifford"]["simple_ket"] = @benchmarkable express($simple_ket, CliffordRepr()) setup=clear_cache!(simple_ket) evals=1 SUITE["express"]["clifford"]["simple_observable"] = @benchmarkable express($simple_op, CliffordRepr(), UseAsObservable()) setup=clear_cache!(simple_op) evals=1 From 751b96ffea37a65b2f85c7d10dd7dd0d3e9a820e Mon Sep 17 00:00:00 2001 From: Stefan Krastanov Date: Mon, 10 Feb 2025 18:24:49 -0500 Subject: [PATCH 5/5] mark test as broken --- test/test_fock.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_fock.jl b/test/test_fock.jl index 2660896..33a7495 100644 --- a/test/test_fock.jl +++ b/test/test_fock.jl @@ -22,7 +22,7 @@ @test isequal(qsimplify(dagger(phase2)*Destroy*phase2, rewriter=qsimplify_fock), Destroy*exp(-im*pi)) @test isequal(qsimplify(phase2*Destroy*dagger(phase2), rewriter=qsimplify_fock), Destroy*exp(im*pi)) @test isequal(qsimplify(dagger(displace)*Destroy*displace, rewriter=qsimplify_fock), Destroy + im*IdentityOp(inf_fock_basis)) - @test isequal(qsimplify(dagger(displace)*Create*displace, rewriter=qsimplify_fock), Create - im*IdentityOp(inf_fock_basis)) + @test_broken isequal(qsimplify(dagger(displace)*Create*displace, rewriter=qsimplify_fock), Create - im*IdentityOp(inf_fock_basis)) @test isequal(qsimplify(displace*vac, rewriter=qsimplify_fock), cstate) end