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

Port ElidePermutations transpiler pass to Rust #13094

Merged
merged 20 commits into from
Oct 3, 2024

Conversation

alexanderivrii
Copy link
Contributor

@alexanderivrii alexanderivrii commented Sep 5, 2024

Summary

Closes #12336.

This PR reimplements most of the logic of the ElidePermutations transpiler pass in Rust (the only thing missing is updating the passmanager's property set to account for the new mapping, this is still done in the Python space).

The Rust code also corrects a problem in the Python code where the qubit mapping was not updated correctly in the presence of permutation gates over a subset of qubits -- it's really scary how broken it was and that none of our tests were catching this (and I have added an extra python test that would exhibit the bug).

On one simple test with 100,000 CX-gates and 99,800 SWAP-gates (multiple iterating layers of CX-gates and SWAP-gates), the runtime is improved from 1.388 seconds to 0.094 seconds -- about 10x speedup; and on another simple quantum-volume-like test (multiple iterating layers of random unitary and permutation gates) the runtime is improved from 0.128 seconds to 0.020 seconds -- about 5x speedup.

Details and comments

I have needed to expose some of the functionality from DAGCircuit, First, I needed the pure Rust version of the function count_ops() which I have copied from some other PR, most probably from #13013 (thus it's probably best to wait till this merges and rebase the code on top of it). Second, I needed to make some of the functions public, namely: push_back, topological_op_nodes and copy_empty_like. Third, I needed the setter variant set_qargs (and we already had get_qargs), and I also added set_cargs for consistency.

Thanks to @jakelishman and @Cryoris for help and suggestions!

@alexanderivrii alexanderivrii requested a review from a team as a code owner September 5, 2024 13:30
@qiskit-bot
Copy link
Collaborator

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

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

@alexanderivrii alexanderivrii added this to the 1.3 beta milestone Sep 5, 2024
@alexanderivrii alexanderivrii added the mod: transpiler Issues and PRs related to Transpiler label Sep 5, 2024
@coveralls
Copy link

coveralls commented Sep 8, 2024

Pull Request Test Coverage Report for Build 11158897921

Details

  • 76 of 78 (97.44%) changed or added relevant lines in 6 files are covered.
  • 6 unchanged lines in 1 file lost coverage.
  • Overall coverage increased (+0.02%) to 88.901%

Changes Missing Coverage Covered Lines Changed/Added Lines %
crates/accelerate/src/elide_permutations.rs 68 70 97.14%
Files with Coverage Reduction New Missed Lines %
crates/qasm2/src/lex.rs 6 93.23%
Totals Coverage Status
Change from base Build 11157232318: 0.02%
Covered Lines: 74349
Relevant Lines: 83631

💛 - Coveralls

Copy link
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.

Just a few small comments.

let mapped_qubits = new_dag.set_qargs(&mapped_qargs);
mapped_inst.qubits = mapped_qubits;
new_dag.push_back(py, mapped_inst)?;
let params = inst.params.clone();
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this still needed? Or can we directly do inst.params.as_deref().cloned() in the stuct initializer?

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 catch, this is a remnant of my own failed attempts to clone params correctly. Fixed in 8209757.

Copy link
Contributor

Choose a reason for hiding this comment

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

Sounds good. We should probably (in a separate PR) expose a method on PackedInstruction as well which just returns self.params.as_deref() for convenience.

Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Contributor

@kevinhartman kevinhartman Oct 1, 2024

Choose a reason for hiding this comment

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

Hmm. Perhaps what I'm suggesting would be more confusing, then. The params_view method returns a &[Param] slice, but what we'd need here is the owned representation of parameters stored by DAGCircuit (Option<SmallVec<[Param; 3]>>).

That makes me think we may want to consider changing DAGCircuit::apply_operation_{back,front} to take &[Param] instead of owned data. It'd be less efficient for callers that happen to already have owned parameters to move in during the apply, but it's certainly a cleaner interface and hides what is otherwise an implementation detail for how DAGs store parameters.

Copy link
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. Thanks for the changes (and for trying out the new Rust-facing DAGCircuit::apply_operation_back!).

@@ -0,0 +1,5 @@
---
features_transpiler:
- |
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we haven't actually written release notes like this for any (most of?) the other passes being ported, have we? IMO, we can leave this in for now and the release manager (whoever that ends up being) can just remove this if it's out of place.

@kevinhartman kevinhartman enabled auto-merge October 1, 2024 15:29
@kevinhartman kevinhartman added this pull request to the merge queue Oct 3, 2024
Merged via the queue into Qiskit:main with commit cbb4d5d Oct 3, 2024
15 checks passed
@alexanderivrii alexanderivrii deleted the elide-permutations-in-rust branch October 4, 2024 08:03
ElePT pushed a commit to ElePT/qiskit that referenced this pull request Oct 7, 2024
* initial commit

* Rust docstring improvements

* lint

* restoring elided comment

* explicitlt setting dtype=int for permutation gates

* another attempt

* fmt after merge

* update after merge + comment from code review

* switching to apply_operation_back

* Comments from code review

* fix using params

---------

Co-authored-by: Kevin Hartman <[email protected]>
@ShellyGarion ShellyGarion added the Changelog: New Feature Include in the "Added" section of the changelog label Nov 5, 2024
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
Projects
Status: done
Development

Successfully merging this pull request may close these issues.

Port ElidePermutations to Rust
7 participants