Skip to content

Avoid py token usage in the common path for circuit_to_dag#14589

Merged
mtreinish merged 3 commits intoQiskit:mainfrom
mtreinish:hide-the-py-circ-to-dag
Jul 7, 2025
Merged

Avoid py token usage in the common path for circuit_to_dag#14589
mtreinish merged 3 commits intoQiskit:mainfrom
mtreinish:hide-the-py-circ-to-dag

Conversation

@mtreinish
Copy link
Copy Markdown
Member

Summary

This commit adjusts the Python usage in the DAGCircuit::from_circuit_data code paths. Most of the data model is in Rust at this point with the exception of things explicitly defined in Python (ie a custom gate in Python), ParameterExpression, and control flow. While the latter two are in progress (see #13267 and #13271) we don't need to block the development of C API features that depend on circuit->dag conversion. The Python usage in this code path is around parameterized global phase and deepcopying custom python gates. Neither of these are possible from C because they're in Python and not exposed to C. This commit removes the py token from the function signatures and actively acquires the gil inline if we're using Python parts of the data model when they're needed.

Details and comments

@mtreinish mtreinish added this to the 2.1.0 milestone Jun 12, 2025
@mtreinish mtreinish requested a review from a team as a code owner June 12, 2025 19:48
@mtreinish mtreinish added Changelog: None Do not include in the GitHub Release changelog. Rust This PR or issue is related to Rust code in the repository C API Related to the C API labels Jun 12, 2025
@qiskit-bot
Copy link
Copy Markdown
Collaborator

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

  • @Qiskit/terra-core

@mtreinish mtreinish force-pushed the hide-the-py-circ-to-dag branch 3 times, most recently from dc8afe6 to 01b6788 Compare June 12, 2025 20:01
This commit adjusts the Python usage in the
DAGCircuit::from_circuit_data code paths. Most of the data model is in
Rust at this point with the exception of things explicitly defined in
Python (ie a custom gate in Python), ParameterExpression, and control
flow. While the latter two are in progress (see Qiskit#13267 and Qiskit#13271) we
don't need to block the development of C API features that depend on
circuit->dag conversion. The Python usage in this code path is around
parameterized global phase and deepcopying custom python gates.
Neither of these are possible from C because they're in Python and not
exposed to C. This commit removes the py token from the function
signatures and actively acquires the gil inline if we're using Python
parts of the data model when they're needed.
kevinhartman
kevinhartman previously approved these changes Jun 12, 2025
Copy link
Copy Markdown
Contributor

@kevinhartman kevinhartman left a comment

Choose a reason for hiding this comment

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

This looks good to me (... and, it's a lot more minimal than I was expecting given your description heh 🙂).

@kevinhartman kevinhartman added this pull request to the merge queue Jun 12, 2025
Comment thread crates/circuit/src/packed_instruction.rs Outdated
@jakelishman jakelishman removed this pull request from the merge queue due to a manual request Jun 12, 2025
@jakelishman
Copy link
Copy Markdown
Member

I removed this from the queue on the basis of the previous comment. I don't mind being overruled and it re-added to the queue, but I think it should be considered first.

I think we should be being a lot more careful about "hide the py". A method which is quite literally asking for Python-space deepcopies in its very name really feels like it should require the GIL to call.

@jakelishman
Copy link
Copy Markdown
Member

Also, is the milestone set right? I'd have assumed this was for 2.2.

@mtreinish mtreinish modified the milestones: 2.1.0, 2.2.0 Jun 12, 2025
@coveralls
Copy link
Copy Markdown

coveralls commented Jun 12, 2025

Pull Request Test Coverage Report for Build 15744392705

Warning: This coverage report may be inaccurate.

This pull request's base commit is no longer the HEAD commit of its target branch. This means it includes changes from outside the original pull request, including, potentially, unrelated coverage changes.

Details

  • 111 of 134 (82.84%) changed or added relevant lines in 11 files are covered.
  • 58 unchanged lines in 6 files lost coverage.
  • Overall coverage increased (+0.01%) to 88.018%

Changes Missing Coverage Covered Lines Changed/Added Lines %
crates/transpiler/src/passes/basis_translator/mod.rs 7 15 46.67%
crates/circuit/src/dag_node.rs 0 15 0.0%
Files with Coverage Reduction New Missed Lines %
crates/circuit/src/symbol_expr.rs 1 73.9%
crates/transpiler/src/passes/unitary_synthesis.rs 1 94.53%
crates/qasm2/src/lex.rs 5 92.23%
crates/qasm2/src/parse.rs 6 97.61%
crates/circuit/src/classical/expr/var.rs 7 93.4%
crates/circuit/src/classical/expr/expr.rs 38 92.06%
Totals Coverage Status
Change from base Build 15740754205: 0.01%
Covered Lines: 84025
Relevant Lines: 95463

💛 - Coveralls

In the previous commit the py token acquisition was moved down into the
PackedInstruction::py_deepcopy() method instead of being the
responsibility of the caller. This decision was made because we only
need the py token in a context where objects defined in Python are
encountered. The goal of hiding the py token is that in a context
without python at all (i.e. the standalone C API) nothing callable from
a pure rust context requires the py token. The token was moved down so
that we only ever try to acquire the GIL in contexts where we have a
python defined object. The method only ever uses it to deep copy in the
case of PackedInstruction containing a Python defined object.

In code review the concern was raised that deepcopy is a purely python
construct and the `py_deepcopy` should very explicitly be the caller's
responsibility to assert they have the GIL by passing the py token. To
address this concern but also enable a Python free path through circuit
to dag conversion this commit moves the `deepcopy()` (and `py_copy()`)
methods up a layer so that they're defined on the Python owned
operations. A new trait `PythonOperation` is added that contains these
methods and the trait is implemented for the Python defined operation
types: `PyGate`, `PyInstruction`, and `PyOperation`. This makes it more
explicit where these methods are callable and makes the python usage
explicit from the caller.
@mtreinish mtreinish changed the title Avoid py token usage in the common path for circuit_to_data Avoid py token usage in the common path for circuit_to_dag Jun 18, 2025
Copy link
Copy Markdown
Contributor

@raynelfss raynelfss left a comment

Choose a reason for hiding this comment

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

This looks good to me!

I thought about suggesting all of the matching to happen within a method or something similar, but with how it looks right now, I don't think there's a way around it considering that we will only call this for certain types of operations. We can always follow it up and think of a better-looking way of doing it.

That said, make sure you update the PRs description to include the PythonOperation trait's description and why it was added :)

@mtreinish mtreinish removed their assignment Jul 3, 2025
@mtreinish
Copy link
Copy Markdown
Member Author

That said, make sure you update the PRs description to include the PythonOperation trait's description and why it was added :)

It's in the commit message for the change: 2e496e6

@mtreinish mtreinish added this pull request to the merge queue Jul 7, 2025
Merged via the queue into Qiskit:main with commit 8cbb31d Jul 7, 2025
26 checks passed
@mtreinish mtreinish deleted the hide-the-py-circ-to-dag branch July 7, 2025 16:04
aaryav-3 pushed a commit to aaryav-3/qiskit that referenced this pull request Oct 21, 2025
)

* Avoid py token usage in the common path for circuit_to_data

This commit adjusts the Python usage in the
DAGCircuit::from_circuit_data code paths. Most of the data model is in
Rust at this point with the exception of things explicitly defined in
Python (ie a custom gate in Python), ParameterExpression, and control
flow. While the latter two are in progress (see Qiskit#13267 and Qiskit#13271) we
don't need to block the development of C API features that depend on
circuit->dag conversion. The Python usage in this code path is around
parameterized global phase and deepcopying custom python gates.
Neither of these are possible from C because they're in Python and not
exposed to C. This commit removes the py token from the function
signatures and actively acquires the gil inline if we're using Python
parts of the data model when they're needed.

* Move deepcopy Python usage up to Python defined types

In the previous commit the py token acquisition was moved down into the
PackedInstruction::py_deepcopy() method instead of being the
responsibility of the caller. This decision was made because we only
need the py token in a context where objects defined in Python are
encountered. The goal of hiding the py token is that in a context
without python at all (i.e. the standalone C API) nothing callable from
a pure rust context requires the py token. The token was moved down so
that we only ever try to acquire the GIL in contexts where we have a
python defined object. The method only ever uses it to deep copy in the
case of PackedInstruction containing a Python defined object.

In code review the concern was raised that deepcopy is a purely python
construct and the `py_deepcopy` should very explicitly be the caller's
responsibility to assert they have the GIL by passing the py token. To
address this concern but also enable a Python free path through circuit
to dag conversion this commit moves the `deepcopy()` (and `py_copy()`)
methods up a layer so that they're defined on the Python owned
operations. A new trait `PythonOperation` is added that contains these
methods and the trait is implemented for the Python defined operation
types: `PyGate`, `PyInstruction`, and `PyOperation`. This makes it more
explicit where these methods are callable and makes the python usage
explicit from the caller.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

C API Related to the C API Changelog: None Do not include in the GitHub Release changelog. Rust This PR or issue is related to Rust code in the repository

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants