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

Make fewer accesses, instruction.operation, in exporter.py #12481

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

jlapeyre
Copy link
Contributor

@jlapeyre jlapeyre commented May 30, 2024

EDIT: To clarify the motivation. This fixes a bug in the exporter that is exposed by #12459 .

Code in qiskit/qasm3/exporter.py uses the object id to track processing gates. But with upcoming changes in #12459 a new object is created every time an operation is accessed within an instruction. Python allows an object's id to be reused after its reference count goes to zero. As a result, sometimes a stored id refers to two different gates (one of them no longer exists as an object) This will cause errors to be raised.

This PR replaces several repeated accesses with a single access. This is also more efficient since each access actually constructs an object.

In particular when testing #12459 a code path is found in which a gate is accessed, its id is cached, it is freed, and another gate is accessed; all with no intervening statements. This PR prevents the first gate object from being freed until after the second gate is accessed and analyzed.

However, this PR does not remove all possible recycling of ids during a code section that uses them to track gate processing. This design should be replaced with a new approach.

Code in qiskit/qasm3/exporter.py uses the object id to track processing
gates. But with upcoming changes in Qiskit#12495 a new object is created every
time an operation is accessed within an instruction. Python allows an object's
id to be reused after its reference count goes to zero. As a result,
sometimes a stored id refers to two different gates (one of them no longer exists
as an object) This will cause errors to be raised.

This PR replaces several repeated accesses with a single access. This is
also more efficient since each access actually constructs an object.

In particular when testing Qiskit#12495 a code path is found in which a
gate is accessed, its id is cached, it is freed, and another gate is accessed;
all with no intervening statements. This PR prevents the first gate object
from being freed until after then second gate is accessed and analyzed.

However, this PR does not remove all possible recycling of ids during a code
section that uses them to track gate processing. This design should be replaced
with a new approach.
@jlapeyre jlapeyre requested a review from a team as a code owner May 30, 2024 13:45
@qiskit-bot
Copy link
Collaborator

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

  • @Qiskit/terra-core

@coveralls
Copy link

Pull Request Test Coverage Report for Build 9304610456

Details

  • 45 of 45 (100.0%) changed or added relevant lines in 1 file are covered.
  • 20 unchanged lines in 3 files lost coverage.
  • Overall coverage decreased (-0.02%) to 89.578%

Files with Coverage Reduction New Missed Lines %
crates/qasm2/src/expr.rs 1 94.02%
crates/qasm2/src/lex.rs 7 91.6%
crates/qasm2/src/parse.rs 12 96.69%
Totals Coverage Status
Change from base Build 9291000954: -0.02%
Covered Lines: 62317
Relevant Lines: 69567

💛 - Coveralls

Copy link
Contributor

@ElePT ElePT left a comment

Choose a reason for hiding this comment

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

I don't think I'm familiar enough with the code to comment on how to avoid the recycling of ids mentioned in the PR description, but the changes from this PR look straightforward to me.

Copy link
Member

@jakelishman jakelishman left a comment

Choose a reason for hiding this comment

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

Given that the exporter is tracking objects by using the id and objects are no longer referentially identical for standard gates (but should be for user-defined gates), I don't think this PR is solving the underlying problem, so there's a pretty high chance that there's paths through, or simple changes we might make in the future that will invalidate it.

If we need the exact id objects to hang around, then we need to be storing at least a ref to the operation in the symbol table, so that the lifetimes of the use of the id (in the table) and the object itself are bound together. That said, given that the symbol tables uses id at all, and that's no longer stable for standard gates, we need to change the symbol table to handle the storage of standard gates without use of the id.

It might be good to look at how hard it is to do that immediately - if we need to merge this as a stop-gap measure, we can, but there's a clear underlying logic bug in the OQ3 exporter that still needs addressing.

@jlapeyre
Copy link
Contributor Author

I don't think this PR is solving the underlying problem

Right, this is what I meant to say with the last line of the opening comment.

I was working kind of quickly, so I didn't think yet of a better solution. But maybe it's not too difficult. I agree that merging this bandaid is not anything near ideal.

@jakelishman
Copy link
Member

#12776 implements the type of fix I was talking about above by rewriting how the symbol table works to remove the assumption that instruction.operation has a stable ID for standard-gate objects.

The other components of this might still be a performance upgrade - I haven't checked - so this might still be something we want to merge.

@1ucian0
Copy link
Member

1ucian0 commented Jul 18, 2024

Should this PR be closed in favor of #12776 ?

@jlapeyre jlapeyre marked this pull request as draft July 20, 2024 00:06
@jlapeyre
Copy link
Contributor Author

@1ucian0, #12776 (comment) is a comment on the utility of this PR.

  • Rewrite OpenQASM 3 exporter symbol table #12776 heavily edits the same code that I touch here. So trying to merge this would not be clean.
  • I doubt the performance benefit would be significant. Given this and the previous item, I don't want to invest time in this at present (if ever).

But I'd prefer to wait til #12776 lands in case @jakelishman wants to weigh in.

In the meantime, I converted this to a draft to backburner it.

@1ucian0
Copy link
Member

1ucian0 commented Jul 22, 2024

Sounds good! Let's do that: wait for the merge of #12776 and reevaluate this one.

@1ucian0 1ucian0 added the on hold Can not fix yet label Jul 22, 2024
@1ucian0 1ucian0 added this to the 1.3.0 milestone Jul 22, 2024
@mtreinish mtreinish removed this from the 1.3.0 milestone Nov 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
on hold Can not fix yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants