Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable PyO3 in cargo unit tests. #13169

Open
wants to merge 19 commits into
base: main
Choose a base branch
from

Conversation

kevinhartman
Copy link
Contributor

@kevinhartman kevinhartman commented Sep 17, 2024

Summary

At present, most of our core data structures like DAGCircuit internally rely on the Python interpreter in some way, which has so far prevented us from writing Rust-based unit tests. Up to this point, we've gotten away with depending on our Python-based test coverage to exercise Rust code internally, but this is quickly becoming insufficient as we add more Rust-only API surface.

This PR does a few things to enable the use of the Python interpreter and load Qiskit's Python code into it:

  • The test executable is built with PyO3 feature auto-initialize, which initializes the free-threaded Python interpreter. This enables the use of Python::with_gil and thus access to a Python token from within tests.
  • We disable miri for such tests, since it is not compatible (e.g. #[cfg(not(miri))]).
  • We set the PYTHONUSERBASE environment variable to the active venv's directory. This allows the Python interpreter baked into the test executable to locate the Python qiskit module.
  • A new tox env has been added to orchestrate this. To run Rust tests, simply invoke tox -erust.

Details and comments

As an example, this PR adds unit tests for DAGCircuit::push_back and DAGCircuit::push_front. We really ought to add more testing for the other new Rust-facing methods (e.g. DAGCircuit::extend via additional PRs).

As more of Qiskit's core is ported to Rust, our reliance on the Python interpreter from Rust code should eventually be overcome, and at that point we shouldn't need these changes anymore.

@kevinhartman kevinhartman requested a review from a team as a code owner September 17, 2024 17:12
@qiskit-bot
Copy link
Collaborator

One or more of the following people are relevant to this code:

  • @Qiskit/terra-core
  • @kevinhartman
  • @mtreinish

@coveralls
Copy link

coveralls commented Sep 17, 2024

Pull Request Test Coverage Report for Build 11673899398

Details

  • 0 of 0 changed or added relevant lines in 0 files are covered.
  • 4 unchanged lines in 2 files lost coverage.
  • Overall coverage increased (+0.02%) to 88.784%

Files with Coverage Reduction New Missed Lines %
crates/accelerate/src/unitary_synthesis.rs 1 92.2%
crates/qasm2/src/lex.rs 3 92.98%
Totals Coverage Status
Change from base Build 11669445061: 0.02%
Covered Lines: 76777
Relevant Lines: 86476

💛 - Coveralls

@jakelishman
Copy link
Member

If you enable the pyo3/auto-initialize feature during the test-suite build, then the pyo3::prepare_freethreaded_python calls won't be necessary. Don't know if you had other work around the test harness planned, though.

@kevinhartman kevinhartman changed the title [WIP] Proof of concept for using PyO3 in cargo unit tests. Enable PyO3 in cargo unit tests. Oct 2, 2024
Copy link
Member

@mtreinish mtreinish left a comment

Choose a reason for hiding this comment

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

Overall this looks great to me, I really am looking forward to having an established pattern for doing more involved rust testing. Especially as we're moving more into rust. I left a few inline comments, mostly nits in the docs and a question in the tests. The only concern I have right now is that we're defaulting to building the python extension in release mode for rust testing and I feel like we should be defaulting to debug mode for the extension when in a rust testing context. Not because I think we need the debug symbols or optimizations disabled, but just to reduce the compile time since the extension is only there to make python work and we shouldn't really be concerned with the runtime performance of it in a rust testing context.

CONTRIBUTING.md Outdated Show resolved Hide resolved
Comment on lines +595 to +597
```bash
tox -erust
```
Copy link
Member

Choose a reason for hiding this comment

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

My only concern here is that this results in building Qiskit from source twice on every execution. I'm not sure there is a way around this since we need the python extension built to be able to call it via python in the rust tests it just is pretty slow. We should probably build in debug mode by default in tox and for rust testing by default.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've enabled debug mode by default for the rust env's package environment in 6856adb.

I also documented --skip-pkg-install as an option for running without rebuilding Qiskit when invoking tox -erust, and I've explained there that this is only an option if you've already built the current working tree: 4813a7c

CONTRIBUTING.md Outdated
Comment on lines 599 to 600
You can also execute them directly in your own virtual environment with these
commands (which is what the ``tox`` env is doing under the hood):
Copy link
Member

Choose a reason for hiding this comment

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

There is a path to running without a virtual environment, but that's probably not good to encourage because it means people will be installing a dev version of qiskit in their system site packages. It might be good to add a sentence here explaining you should make a venv for testing in this case.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point. I've reworded this section to guide users to first create and activate a virtual environment if they're running without tox.

234b6a5

CONTRIBUTING.md Outdated Show resolved Hide resolved
CONTRIBUTING.md Outdated

```bash
cargo test --no-default-features
python setup.py build_rust --release --inplace
Copy link
Member

Choose a reason for hiding this comment

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

I'd actually change this to not include --release by default. That just increases the build time and we shouldn't be bottlenecked on the python extension's execution time in rust tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Should be done in 234b6a5 as well.

[testenv:rust]
basepython = python3
setenv =
PYTHONUSERBASE={envdir}
Copy link
Member

Choose a reason for hiding this comment

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

The default tox configuration will build in release mode, I think for rust testing we should use debug mode by default.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done in 6856adb.

crates/circuit/src/dag_circuit.rs Show resolved Hide resolved
@kevinhartman
Copy link
Contributor Author

This should be ready to go, @mtreinish.

The Rust tests for DAGCircuit added in the PR can be seen passing in CI here: https://dev.azure.com/qiskit-ci/qiskit/_build/results?buildId=62018&view=logs&j=bf26c3d0-9b88-5f67-96f4-43488114ea6d&t=5c74c3c4-ab20-5140-0e04-11aec0505a88&l=148

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants