perf(hafnian): Replace implementation#291
Merged
Merged
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #291 +/- ##
==========================================
- Coverage 95.41% 95.28% -0.13%
==========================================
Files 61 60 -1
Lines 3356 3266 -90
==========================================
- Hits 3202 3112 -90
Misses 154 154 ☔ View full report in Codecov by Sentry. |
**Problem** The PiquassoBoost version of the (loop)hafnian is very efficient, but the implementation in Piquasso itself is not, the performance gap is large between the two implementations. **Solution** An efficient version of the (loop)hafnian function got implemented using Numba and the PiquassoBoost code translated from C++ to Python. The power trace algorithm has been copied using Glynn-type iterations, which is enabled by default in PiquassoBoost. Of course, this does not replace the PiquassoBoost implementation, only narrows the performance gap between the two, to provide relatively fast (loop)hafnian calculations without the need of installing PiquassoBoost. `numba` is added as a dependency. The `piquasso/_math/hafnian` folder is ignored in Codecov, since it could not track code compiled with Numba.
Kolarovszki
pushed a commit
that referenced
this pull request
Nov 3, 2025
…to >=4.0,<5.3 (#532) Updates the requirements on [pytest-benchmark](https://github.com/ionelmc/pytest-benchmark) to permit the latest version. <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/ionelmc/pytest-benchmark/blob/master/CHANGELOG.rst">pytest-benchmark's changelog</a>.</em></p> <blockquote> <h2>5.2.0 (2025-10-30)</h2> <ul> <li>Added support for a per-round <code>teardown</code> function to pedantic mode. Contributed Patrick Winter by <code>[#264](ionelmc/pytest-benchmark#264) <https://github.com/ionelmc/pytest-benchmark/pull/264></code>_.</li> <li>Added <code>--benchmark-time-unit</code> option. Contributed by Tony Kuo in <code>[#281](ionelmc/pytest-benchmark#281) <https://github.com/ionelmc/pytest-benchmark/pull/281></code>_.</li> <li>Fixed deprecated hook examples in docstrings. Contributed by Ali-Akber Saifee in <code>[#284](ionelmc/pytest-benchmark#284) <https://github.com/ionelmc/pytest-benchmark/pull/284></code>_.</li> <li>Changed <code>--benchmark-compare-fail</code> to accept percentages higher than 100%. Contributed by Ben Avrahami in <code>[#290](ionelmc/pytest-benchmark#290) <https://github.com/ionelmc/pytest-benchmark/pull/280></code>_.</li> <li>Added minimal typing support. Contributed by Sorin Sbarnea in <code>[#290](ionelmc/pytest-benchmark#290) <https://github.com/ionelmc/pytest-benchmark/pull/290></code>_.</li> <li>Fixed support for Python 3.9. Contributed by Enno Gotthold in <code>[#291](ionelmc/pytest-benchmark#291) <https://github.com/ionelmc/pytest-benchmark/pull/291></code>_.</li> <li>Replaced the complicated and broken code of <code>pytest_benchmark.utils.clonefunc</code> with a simple return of the input. That function was supposed to allow benchmarking with the cost of PyPy JIT included but it's a hassle to maintain.</li> <li>Moved the instrumentation pause outside the round loops (in addition to tracing, profiling is paused too). Pedantic mode will keep doing this per round (as the user manually controls the round count). This is necessary because in some scenarios setting and unsetting the tracer too much will overflow an internal counter (found to cause "OverflowError: events set too many times" at least on Python 3.13).</li> </ul> <h2>5.1.0 (2024-10-30)</h2> <ul> <li>Fixed broken hooks handling on pytest 8.1 or later (the <code>TypeError: import_path() missing 1 required keyword-only argument: 'consider_namespace_packages'</code> issue). Unfortunately this sets the minimum supported pytest version to 8.1.</li> </ul> <h2>5.0.1 (2024-10-30)</h2> <ul> <li>Fixed bad fixture check that broke down then <code>nbmake <https://pypi.org/project/nbmake/></code>_ was enabled.</li> </ul> <h2>5.0.0 (2024-10-29)</h2> <ul> <li> <p>Dropped support for now EOL Python 3.8. Also moved tests suite to only test the latest pytest versions (8.3.x).</p> </li> <li> <p>Fix generate parametrize tests benchmark csv report errors (issue <code>[#268](ionelmc/pytest-benchmark#268) <https://github.com/ionelmc/pytest-benchmark/issues/268></code><em>). Contributed by Johnny Huang in <code>[#269](ionelmc/pytest-benchmark#269) <https://github.com/ionelmc/pytest-benchmark/pull/269></code></em>.</p> </li> <li> <p>Added the <code>--benchmark-time-unit</code> cli option for overriding the measurement unit used for display. Contributed by Tony Kuo in <code>[#257](ionelmc/pytest-benchmark#257) <https://github.com/ionelmc/pytest-benchmark/pull/257></code>_.</p> </li> <li> <p>Fixes spelling in some help texts. Contributed by Eugeniy in <code>[#267](ionelmc/pytest-benchmark#267) <https://github.com/ionelmc/pytest-benchmark/pull/267></code>_.</p> </li> <li> <p>Added new cprofile options:</p> <ul> <li><code>--benchmark-cprofile-loops=LOOPS</code> - previously profiling only ran the function once, this allow customization.</li> <li><code>--benchmark-cprofile-top=COUNT</code> - allows showing more rows.</li> <li><code>--benchmark-cprofile-dump=[FILENAME-PREFIX]</code> - allows saving to a file (that you can load in <code>snakeviz <https://pypi.org/project/snakeviz/></code><em>, <code>RunSnakeRun <https://pypi.org/project/RunSnakeRun/></code></em> or other tools).</li> </ul> </li> <li> <p>Removed hidden dependency on <code>py.path <https://pypi.org/project/py/></code>_ (replaced with pathlib).</p> </li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/ionelmc/pytest-benchmark/commit/5a164cec3b7290e30c38cb4ea32ac4e1be65ec87"><code>5a164ce</code></a> Bump version: 5.1.0 → 5.2.0</li> <li><a href="https://github.com/ionelmc/pytest-benchmark/commit/abfb09bab2c1655e269254c10ed54fc5f8146c0d"><code>abfb09b</code></a> Reword the last 2 changes.</li> <li><a href="https://github.com/ionelmc/pytest-benchmark/commit/f8c081b2aec1ee295b4bfa20e03bdd46d6a9804f"><code>f8c081b</code></a> Bump hooks and fix mypy complaint.</li> <li><a href="https://github.com/ionelmc/pytest-benchmark/commit/604c2e7ee470fffe1e4a70664309d0c52029a591"><code>604c2e7</code></a> Replace all the manual tracer unset/restore with a context manager, and move ...</li> <li><a href="https://github.com/ionelmc/pytest-benchmark/commit/0e247fd6f651c8d8e8d04f4606d0c27b6e417c7e"><code>0e247fd</code></a> Do not unset/set the tracer/profiler if there's no previous one.</li> <li><a href="https://github.com/ionelmc/pytest-benchmark/commit/64ae56d32b1a17fcbfccc6d2dc088cd237c9eea5"><code>64ae56d</code></a> Rename to match convention from cprofile mode.</li> <li><a href="https://github.com/ionelmc/pytest-benchmark/commit/347d84d152f6cc334f0cb0a7671e1600ab2bb6c0"><code>347d84d</code></a> Also disable other profiler.</li> <li><a href="https://github.com/ionelmc/pytest-benchmark/commit/68687926c06c972a5d3f04fe5ce24ddd6329a1bc"><code>6868792</code></a> Make cprofile mode disable tracers, just like regular bench mode. Should make...</li> <li><a href="https://github.com/ionelmc/pytest-benchmark/commit/8e735b23798cc8cf59239f2a0e1f063b5b81e66b"><code>8e735b2</code></a> Nuke the now-broken clonefunc with a identity function. It's currently broken...</li> <li><a href="https://github.com/ionelmc/pytest-benchmark/commit/cecc6ef394adde005ce23b8734bbc1d0ef4dc267"><code>cecc6ef</code></a> Fix some badges.</li> <li>Additional commits viewable in <a href="https://github.com/ionelmc/pytest-benchmark/compare/v4.0.0...v5.2.0">compare view</a></li> </ul> </details> <br /> Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The PiquassoBoost version of the (loop)hafnian is very efficient, but the implementation in Piquasso itself is not, the performance gap is large between the two implementations.
Solution
An efficient version of the (loop)hafnian function got implemented using Numba and the PiquassoBoost code translated from C++ to Python. The power trace algorithm has been copied using Glynn-type iterations, which is enabled by default in PiquassoBoost. Of course, this does not replace the PiquassoBoost implementation, only narrows the performance gap between the two, to provide relatively fast (loop)hafnian calculations without the need of installing PiquassoBoost.
numbais added as a dependency.The
piquasso/_math/hafnianfolder is ignored in Codecov, since it could not track code compiled with Numba.