Skip to content

Add micro-benchmarks for MPS ApplyGate methods - #1118

Open
KrishGopi1 wants to merge 3 commits into
quantumlib:mainfrom
KrishGopi1:mps-benchmarks
Open

KrishGopi1 wants to merge 3 commits into
quantumlib:mainfrom
KrishGopi1:mps-benchmarks

Conversation

@KrishGopi1

Copy link
Copy Markdown
Contributor

Part of #373.

Summary

Adds Google Benchmark micro-benchmarks for the MPS simulator's gate
application methods.

The benchmarks cover:

  • ApplyGate1 at the left edge, middle, and right edge of a 10-qubit MPS
  • ApplyGate2 at the left edge, middle, and right edge
  • Bond dimensions 4, 16, and 64

The MPS states are initialized with random values to provide a
non-trivial workload.

Running

make benchmarks        # build
make run-benchmarks    # build and run

Requires Google Benchmark (e.g. apt install libbenchmark-dev). Eigen is
fetched by the existing eigen target.

Results

Baseline from the default make benchmarks build (-O3, no -march
flags), median of 5 runs on a 16-core x86 CPU at ~3.8 GHz. Absolute times
vary by machine and by roughly ±10% between runs.

Case D=4 D=16 D=64
ApplyGate1, left 14 ns 28 ns 94 ns
ApplyGate1, middle 41 ns 0.41 µs 5.9 µs
ApplyGate1, right 18 ns 33 ns 124 ns
ApplyGate2, left 1.2 µs 3.5 µs 16 µs
ApplyGate2, middle 27 µs 0.16 ms 5.7 ms
ApplyGate2, right 1.4 µs 3.9 µs 21 µs

Profiling

Timing the SVD in isolation, on a product of two random blocks of the
shape ApplyGate2 decomposes, under the same flags as the benchmark:
Eigen's BDCSVD takes roughly 80% (D=4), 83% (D=16), and 93% (D=64) of a
middle-position ApplyGate2 call. The block matrix multiplication takes
about 5-6% at each size.

Changing the BDCSVD switch size did not help, and JacobiSVD was about
9x (D=16) to 12x (D=64) slower.

Substantial further speedups of ApplyGate2 would likely require
investigating the SVD implementation itself.

No MPS simulator implementation code is changed by this PR.

🤖 Generated with Claude Code

Adds Google Benchmark micro-benchmarks for MPSSimulator::ApplyGate1 and
ApplyGate2 at the left edge, middle, and right edge of the MPS, across
several bond dimensions, along with `make benchmarks` and
`make run-benchmarks` targets.

Part of quantumlib#373.
@github-actions github-actions Bot added the size: M 50< lines changed <250 label Oct 5, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a micro-benchmark suite for MPSSimulator::ApplyGate* under a new benchmarks/ directory, along with the necessary Makefiles to build and run them. The review feedback highlights a critical issue in BM_ApplyGate2 where the state is modified in-place inside the benchmark loop, leading to exponential norm decay and numerical underflow. To resolve this and ensure accurate benchmark results, the reviewer suggests copying a pristine state template using std::memcpy at each iteration and adding the header.

Comment on lines +17 to +19
#include <cstdint>
#include <random>
#include <vector>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Add <cstring> to the includes to support std::memcpy for resetting the state in BM_ApplyGate2.

Suggested change
#include <cstdint>
#include <random>
#include <vector>
#include <cstdint>
#include <cstring>
#include <random>
#include <vector>
References
  1. Google C++ Style Guide requires standard library headers to be sorted alphabetically. (link)

Comment thread benchmarks/mps_simulator_benchmark.cc
@KrishGopi1

Copy link
Copy Markdown
Contributor Author

Thanks for the review. I checked the concern about repeated in-place application in BM_ApplyGate2 and didn't change the benchmark loop. I added a code comment instead.

  • State decay: over up to 20,000 consecutive ApplyGate2 calls (every bond dimension and position used here), the touched tensors' norm drops 1-3% in the first few iterations and then stays flat. It does not decay to zero or subnormal values.
  • Timing: I compared in-place repetition against restoring the initial state before every iteration, with the copy cost measured and subtracted. The two agree within noise (between -7% and +12%, no consistent direction). For example, at D=16 in the middle: 168 µs in place vs 181 µs with a fresh state.
  • Why not PauseTiming/ResumeTiming: for the cheapest cases (~1 µs) the pause/resume overhead is comparable to the quantity being measured, and the copy costs ~9 µs at D=64, which is not negligible next to the 16-22 µs edge cases. That would make the numbers less accurate, not more.

The comment added in 73fe522 records that the in-place loop matches the reset-each-iteration timings for the gate and sizes used.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size: M 50< lines changed <250

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant