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

Avoid operator creation in transpiler #12826

Merged
merged 4 commits into from
Jul 31, 2024

Conversation

jakelishman
Copy link
Member

Summary

This removes very nearly all of the use of DAGOpNode.op in the default transpiler paths. The sole exception is in InverseCancellation, which currently would involve some quite awkward gymnastics for little near-term benefit. The pass should move fully to Rust soon, making it not worth the effort.

Most of the tricks here involve using the knowledge that most operations will involve only Rust-space standard gates, and that these cannot be control-flow operations.

Details and comments

This always includes a reno for a couple of the new methods added to DAGOpNode and CircuitInstruction.

I measured this as being ~25% faster for some toy workloads at transpilation levels 0 and 1, probably mostly driven by the new methods letting us avoid a lot of isinstance checks in most cases.

@jakelishman jakelishman added Changelog: New Feature Include in the "Added" section of the changelog mod: transpiler Issues and PRs related to Transpiler labels Jul 26, 2024
@qiskit-bot
Copy link
Collaborator

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

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

@jakelishman jakelishman marked this pull request as draft July 26, 2024 16:59
This removes very nearly all of the use of `DAGOpNode.op` in the default
transpiler paths.  The sole exception is in `InverseCancellation`, which
currently would involve some quite awkward gymnastics for little
near-term benefit. The pass should move fully to Rust soon, making it
not worth the effort.

Most of the tricks here involve using the knowledge that most operations
will involve only Rust-space standard gates, and that these cannot be
control-flow operations.
@jakelishman jakelishman marked this pull request as ready for review July 29, 2024 17:26
@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 Jul 29, 2024

Pull Request Test Coverage Report for Build 10184959106

Details

  • 108 of 114 (94.74%) changed or added relevant lines in 15 files are covered.
  • 24 unchanged lines in 3 files lost coverage.
  • Overall coverage increased (+0.05%) to 89.703%

Changes Missing Coverage Covered Lines Changed/Added Lines %
qiskit/transpiler/passes/synthesis/high_level_synthesis.py 25 26 96.15%
crates/circuit/src/circuit_instruction.rs 11 16 68.75%
Files with Coverage Reduction New Missed Lines %
qiskit/transpiler/passes/basis/basis_translator.py 1 97.44%
crates/qasm2/src/lex.rs 5 91.98%
crates/qasm2/src/parse.rs 18 96.69%
Totals Coverage Status
Change from base Build 10184756963: 0.05%
Covered Lines: 67142
Relevant Lines: 74849

💛 - Coveralls

mtreinish
mtreinish previously approved these changes Jul 31, 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 LGTM, I'm happy to wrap up this thread of workarounds before we start migrating passes to rust (which will be doing essentially this but without the language barrier). Just one inline comment but something that's applicable to a bunch of places, basically we can use the name of a control flow op instead of an isinstance check to defer the op creation until we actually use it. Although as those are always PyInstruction it doesn't really matter from a performance perspective as we always have a cached pyobject at that point. So I'm fine merging this as-is if you don't think it's important. Feel free to just enqueue this for merge in that case.

@@ -37,7 +37,7 @@ class MultiQEncountered(Exception):

def _visit(dag, weight, wire_map):
for node in dag.op_nodes(include_directives=False):
if isinstance(node.op, ControlFlowOp):
if node.is_control_flow():
if isinstance(node.op, ForLoopOp):
Copy link
Member

Choose a reason for hiding this comment

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

You could avoid the op usage here too if you did:

Suggested change
if isinstance(node.op, ForLoopOp):
if node.name == "for_loop":

@mtreinish mtreinish added this to the 1.2.0 milestone Jul 31, 2024
@mtreinish mtreinish enabled auto-merge July 31, 2024 16:28
@mtreinish mtreinish added this pull request to the merge queue Jul 31, 2024
Merged via the queue into Qiskit:main with commit 0afb06e Jul 31, 2024
15 checks passed
@mtreinish mtreinish added the stable backport potential The bug might be minimal and/or import enough to be port to stable label Jul 31, 2024
mergify bot pushed a commit that referenced this pull request Jul 31, 2024
* Avoid operator creation in transpiler

This removes very nearly all of the use of `DAGOpNode.op` in the default
transpiler paths.  The sole exception is in `InverseCancellation`, which
currently would involve some quite awkward gymnastics for little
near-term benefit. The pass should move fully to Rust soon, making it
not worth the effort.

Most of the tricks here involve using the knowledge that most operations
will involve only Rust-space standard gates, and that these cannot be
control-flow operations.

* Fix `HighLevelSynthesis` fast path

---------

Co-authored-by: Matthew Treinish <mtreinish@kortar.org>
(cherry picked from commit 0afb06e)
github-merge-queue bot pushed a commit that referenced this pull request Jul 31, 2024
* Avoid operator creation in transpiler

This removes very nearly all of the use of `DAGOpNode.op` in the default
transpiler paths.  The sole exception is in `InverseCancellation`, which
currently would involve some quite awkward gymnastics for little
near-term benefit. The pass should move fully to Rust soon, making it
not worth the effort.

Most of the tricks here involve using the knowledge that most operations
will involve only Rust-space standard gates, and that these cannot be
control-flow operations.

* Fix `HighLevelSynthesis` fast path

---------

Co-authored-by: Matthew Treinish <mtreinish@kortar.org>
(cherry picked from commit 0afb06e)

Co-authored-by: Jake Lishman <jake.lishman@ibm.com>
@jakelishman jakelishman deleted the avoid-operation-creation branch July 31, 2024 22:20
Procatv pushed a commit to Procatv/qiskit-terra-catherines that referenced this pull request Aug 1, 2024
* Avoid operator creation in transpiler

This removes very nearly all of the use of `DAGOpNode.op` in the default
transpiler paths.  The sole exception is in `InverseCancellation`, which
currently would involve some quite awkward gymnastics for little
near-term benefit. The pass should move fully to Rust soon, making it
not worth the effort.

Most of the tricks here involve using the knowledge that most operations
will involve only Rust-space standard gates, and that these cannot be
control-flow operations.

* Fix `HighLevelSynthesis` fast path

---------

Co-authored-by: Matthew Treinish <mtreinish@kortar.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Changelog: New Feature Include in the "Added" section of the changelog mod: transpiler Issues and PRs related to Transpiler stable backport potential The bug might be minimal and/or import enough to be port to stable
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants