-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feature: Add automated benchmarking to GitHub (#35)
* change: nobraket branch * change: Use multiprocessing Pool rather than ProcessPoolExecutor * feature: Add automated benchmarking to GitHub * fix: Use mmap for statevector for performance boost * fix: Working tests and benchmarks * fix: Point to correct branch * fix: Linters * change: Point at new tagged version * fix: Lower maximum qubit count for GH * fix: Benchmark workflow * fix: Don't commit the output file
- Loading branch information
1 parent
c46167a
commit c5e9bcd
Showing
6 changed files
with
247 additions
and
39 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
name: Benchmark | ||
|
||
on: | ||
push: | ||
branches: [ main ] | ||
pull_request: | ||
|
||
jobs: | ||
benchmark: | ||
runs-on: ubuntu-latest | ||
timeout-minutes: 30 | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- name: Install juliaup | ||
uses: julia-actions/[email protected] | ||
with: | ||
channel: '1' | ||
- name: Update Julia registry | ||
shell: julia --project=. --color=yes {0} | ||
run: | | ||
using Pkg | ||
Pkg.Registry.update() | ||
- name: Set up Python | ||
uses: actions/setup-python@v5 | ||
with: | ||
python-version: 3.9 | ||
- name: Install dependencies | ||
run: | | ||
pip install -e .[test] # to put juliapkg.json in sys.path | ||
python -c 'import juliacall' # force install of all deps | ||
- name: Benchmark | ||
run: | | ||
pytest -n 0 benchmark/benchmark.py --benchmark-json=benchmark/output.json | ||
- name: Store benchmark result | ||
uses: benchmark-action/github-action-benchmark@v1 | ||
with: | ||
name: Python Benchmark with pytest-benchmark | ||
tool: 'pytest' | ||
output-file-path: benchmark/output.json | ||
github-token: ${{ secrets.GITHUB_TOKEN }} | ||
auto-push: true | ||
# Show alert with commit comment on detecting possible performance regression | ||
alert-threshold: '200%' | ||
comment-on-alert: true | ||
fail-on-alert: true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
import numpy as np | ||
import pytest | ||
from braket.devices import LocalSimulator | ||
from braket.ir.openqasm import Program | ||
|
||
# always the same for repeatability | ||
np.random.seed(0x1C2C6D66) | ||
|
||
batch_size = (10, 100) | ||
n_qubits = range(3, 16) | ||
exact_shots_results = ( | ||
"state_vector", | ||
"density_matrix q[0], q[1]", | ||
"probability", | ||
"expectation z(q[0])", | ||
"variance y(q[0])", | ||
) | ||
nonzero_shots_results = ( | ||
"probability", | ||
"expectation z(q[0])", | ||
"variance y(q[0])", | ||
"sample z(q[0])", | ||
) | ||
|
||
|
||
def ghz(nq: int, result_type: str): | ||
source = f"OPENQASM 3.0;\nqubit[{nq}] q;\nh q[0];\n" | ||
for q in range(1, nq - 1): | ||
source += f"cnot q[0], q[{q}];\n" | ||
|
||
source += f"#pragma braket result {result_type}\n" | ||
return source | ||
|
||
|
||
def qft(nq: int, result_type: str): | ||
source = f"OPENQASM 3.0;\nqubit[{nq}] q;\n" | ||
for q in range(nq - 1): | ||
angle = np.pi / 2.0 | ||
source += f"h q[{q}];\n" | ||
for ctrl_q in range(q + 1, nq - 1): | ||
source += f"cphaseshift({angle}) q[{ctrl_q}], q[{q}];\n" | ||
angle /= 2.0 | ||
|
||
source += f"#pragma braket result {result_type}\n" | ||
return source | ||
|
||
|
||
def run_sim(oq3_prog, sim, shots): | ||
sim.run(oq3_prog, shots=shots) | ||
return | ||
|
||
|
||
def run_sim_batch(oq3_prog, sim, shots): | ||
sim.run_batch(oq3_prog, shots=shots) | ||
return | ||
|
||
|
||
device_ids = ("braket_sv", "braket_sv_v2", "braket_dm", "braket_dm_v2") | ||
|
||
generators = (ghz, qft) | ||
|
||
|
||
@pytest.mark.parametrize("device_id", device_ids) | ||
@pytest.mark.parametrize("nq", n_qubits) | ||
@pytest.mark.parametrize("exact_results", exact_shots_results) | ||
@pytest.mark.parametrize("circuit", generators) | ||
def test_exact_shots(benchmark, device_id, nq, exact_results, circuit): | ||
if device_id in ("braket_dm_v2", "braket_dm") and ( | ||
exact_results in ("state_vector",) or nq > 10 | ||
): | ||
pytest.skip() | ||
if ( | ||
device_id in ("braket_sv",) | ||
and exact_results in ("density_matrix q[0], q[1]",) | ||
and nq >= 17 | ||
): | ||
pytest.skip() | ||
result_type = exact_results | ||
oq3_prog = Program(source=circuit(nq, result_type)) | ||
sim = LocalSimulator(device_id) | ||
benchmark.pedantic(run_sim, args=(oq3_prog, sim, 0), iterations=5, warmup_rounds=1) | ||
|
||
|
||
@pytest.mark.parametrize("device_id", device_ids) | ||
@pytest.mark.parametrize("nq", n_qubits) | ||
@pytest.mark.parametrize("batch_size", batch_size) | ||
@pytest.mark.parametrize("exact_results", exact_shots_results) | ||
@pytest.mark.parametrize("circuit", generators) | ||
def test_exact_shots_batched( | ||
benchmark, device_id, nq, batch_size, exact_results, circuit | ||
): | ||
if device_id in ("braket_dm_v2", "braket_dm") and ( | ||
exact_results in ("state_vector,") or nq >= 5 | ||
): | ||
pytest.skip() | ||
if nq >= 10: | ||
pytest.skip() | ||
# skip all for now as this is very expensive | ||
pytest.skip() | ||
result_type = exact_results | ||
oq3_prog = [Program(source=circuit(nq, result_type)) for _ in range(batch_size)] | ||
sim = LocalSimulator(device_id) | ||
benchmark.pedantic( | ||
run_sim_batch, args=(oq3_prog, sim, 0), iterations=5, warmup_rounds=1 | ||
) | ||
|
||
|
||
shots = (100,) | ||
|
||
|
||
@pytest.mark.parametrize("device_id", device_ids) | ||
@pytest.mark.parametrize("nq", n_qubits) | ||
@pytest.mark.parametrize("shots", shots) | ||
@pytest.mark.parametrize("nonzero_shots_results", nonzero_shots_results) | ||
@pytest.mark.parametrize("circuit", generators) | ||
def test_nonzero_shots(benchmark, device_id, nq, shots, nonzero_shots_results, circuit): | ||
if device_id in ("braket_dm_v2", "braket_dm") and nq > 10: | ||
pytest.skip() | ||
result_type = nonzero_shots_results | ||
oq3_prog = Program(source=circuit(nq, result_type)) | ||
sim = LocalSimulator(device_id) | ||
benchmark.pedantic( | ||
run_sim, args=(oq3_prog, sim, shots), iterations=5, warmup_rounds=1 | ||
) | ||
del sim | ||
|
||
|
||
@pytest.mark.parametrize("device_id", device_ids) | ||
@pytest.mark.parametrize("nq", n_qubits) | ||
@pytest.mark.parametrize("batch_size", batch_size) | ||
@pytest.mark.parametrize("shots", shots) | ||
@pytest.mark.parametrize("nonzero_shots_results", nonzero_shots_results) | ||
@pytest.mark.parametrize("circuit", generators) | ||
def test_nonzero_shots_batched( | ||
benchmark, device_id, nq, batch_size, shots, nonzero_shots_results, circuit | ||
): | ||
if device_id in ("braket_dm_v2", "braket_dm") and nq >= 5: | ||
pytest.skip() | ||
if nq >= 10: | ||
pytest.skip() | ||
|
||
# skip all for now as this is very expensive | ||
pytest.skip() | ||
|
||
result_type = nonzero_shots_results | ||
oq3_prog = [Program(source=circuit(nq, result_type)) for _ in range(batch_size)] | ||
sim = LocalSimulator(device_id) | ||
benchmark.pedantic( | ||
run_sim_batch, args=(oq3_prog, sim, shots), iterations=5, warmup_rounds=1 | ||
) | ||
del sim |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
juliacall==0.9.22 | ||
juliacall==0.9.23 | ||
numpy | ||
amazon-braket-schemas>=1.20.2 | ||
amazon-braket-sdk>=1.83.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
c5e9bcd
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Possible performance regression was detected for benchmark 'Python Benchmark with pytest-benchmark'.
Benchmark result of this commit is worse than the previous benchmark result exceeding threshold
2
.benchmark/benchmark.py::test_exact_shots[ghz-variance y(q[0])-5-braket_dm]
47.12688317610862
iter/sec (stddev: 0
)126.67564965919034
iter/sec (stddev: 0
)2.69
benchmark/benchmark.py::test_exact_shots[ghz-variance y(q[0])-7-braket_dm_v2]
129.69355798623124
iter/sec (stddev: 0
)314.06175057039223
iter/sec (stddev: 0
)2.42
benchmark/benchmark.py::test_exact_shots[qft-density_matrix q[0], q[1]-7-braket_dm_v2]
87.64308105463063
iter/sec (stddev: 0
)266.50541312508136
iter/sec (stddev: 0
)3.04
benchmark/benchmark.py::test_exact_shots[qft-variance y(q[0])-7-braket_dm_v2]
71.77157393221735
iter/sec (stddev: 0
)216.9578320323035
iter/sec (stddev: 0
)3.02
benchmark/benchmark.py::test_nonzero_shots[ghz-expectation z(q[0])-100-12-braket_sv]
36.85871674963592
iter/sec (stddev: 0
)77.28683394669166
iter/sec (stddev: 0
)2.10
benchmark/benchmark.py::test_nonzero_shots[ghz-sample z(q[0])-100-14-braket_sv]
32.64162296029481
iter/sec (stddev: 0
)69.25562955118954
iter/sec (stddev: 0
)2.12
benchmark/benchmark.py::test_nonzero_shots[qft-probability-100-12-braket_sv_v2]
41.04276229808575
iter/sec (stddev: 0
)120.90650474087754
iter/sec (stddev: 0
)2.95
benchmark/benchmark.py::test_nonzero_shots[qft-variance y(q[0])-100-7-braket_dm_v2]
40.14938171679087
iter/sec (stddev: 0
)97.51415359436345
iter/sec (stddev: 0
)2.43
benchmark/benchmark.py::test_nonzero_shots[qft-sample z(q[0])-100-4-braket_sv]
36.76165196218521
iter/sec (stddev: 0
)106.73945899272341
iter/sec (stddev: 0
)2.90
This comment was automatically generated by workflow using github-action-benchmark.