-
Notifications
You must be signed in to change notification settings - Fork 2.3k
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
Pass manager refactoring: add passmanager module #10124
Pass manager refactoring: add passmanager module #10124
Conversation
One or more of the the following people are requested to review this:
|
ddb834c
to
bd93d94
Compare
Pull Request Test Coverage Report for Build 5352619334
💛 - Coveralls |
61cfff8
to
8261a66
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the delay in reviewing this. I took a quick first higher level pass over the PR. I really like the direction this is taking towards making the pass manager more general so we can use it more broadly as transformation recipe. I have a few inline comments so far. My biggest concern is how this is managing the backwards compatibiltiy of things that are moved unchanged from qiskit.transpiler
-> qiskit.passmanager
I feel like there are a couple of missing places where we should have redirects to ensure things still work from transpiler
as is while we're splitting out the passmanager
module.
logger = logging.getLogger(__name__) | ||
|
||
|
||
class BasePassManager(ABC): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the use of ABC here to prevent directly instantiating an instance of BasePassManager
? I didn't see any abstract methods defined in the class to define an interface otherwise.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually a developer needs to attach BasePassManager.PASS_RUNNER
to make it work. In this base class BasePassRunner
is just linked for convenience of type hint, but the base class doesn't provide IR conversion logic. One could also do abstract class property, but I don't like class property.
Alternatively, we can keep BasePassManager._create_running_passmanager
method and make it abstract. However, writing and overriding this method just for difference of pass runner type seems awkward (we can remove this method in the followup PR #10127 ).
The another place where the pass runner type is necessary is run method. We need to dispatch the _run_single_circuit
when input is a single entry, but we cannot safely count entry number because input program is usually iterable, e.g. QuantumCircuit
and ScheduleBlock
. We can get expected input type through above class attribute, i.e.
if isinstance(programs, self.PASS_RUNNER.IN_PROGRAM_TYPE):
# run single runner call
# otherwise we can assume programs are sequence
7e9d4b3
to
729b174
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This LGTM now, thanks for the updates and sorry for the slow turnaround. I left a few comments about release notes but we can just adjust those as part of the release prep.
I was starting to review the code for the pass manager itself and was going to ask a lot of questions about specifics and things that looked really weird to me until I realized most of that was pre-existing and just migrated code. I'll save those reviews for the next PR in the series that refactors the internals
- | | ||
New error baseclass :class:`~qiskit.passmanager.PassManagerError` is introduced. | ||
This will replace :class:`~qiskit.transpiler.TranspilerError` raised in the | ||
pass handling machinery. The TranspilerError is now only used for the errors | ||
related to the failure in handling the quantum circuit or DAG circuit object. | ||
Note that the TranspilerError can be caught by the PassManagerError | ||
because of their class hierarchy. For backward compatibility, | ||
:class:`qiskit.transpiler.PassManager` catches PassManagerError and | ||
re-raises the TranspilerError. This error replacement will be dropped in future. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok I guess an upgrade note is fine for this. I was more just trying to figure out whether this was a call to action for users catching TranspilerError
before or whether we should document it somewhere else. The only other thought I had was maybe as an other
note but this seems like a better place.
releasenotes/notes/add-passmanager-module-3ae30cff52cb83f1.yaml
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left a couple of suggestions on documentation that should be reviewed.
|
||
def __init__(self): | ||
self.requires = [] # List of passes that requires | ||
self.preserves = [] # List of passes that preserves |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My best recollection is that preserves
has not been useful in practice. In fact, as far as I can see, it is not used at all in terra. In contrast, requires
is used a bit. If it were not for backward compatibility, I imagine preserves
would be removed. So I question whether it is a good idea to include this as a feature in the more abstract pass manager. Is it possible to define this attribute instead in BasePass(CommonBasePass)
below?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think for this PR it's ok to preserve preserves
as this is strictly for migrating the common code that already exists into a reusable module. There is a second PR #10127 built on top of this which aims to clean things up. I think we can discuss specifics like that there. I think it would be easier to view this PR as just a code migration for the ease of review. We're not locked into the api here until the final release anyway so there is time to change it post merge
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @jlapeyre , I agree with you. I also observed that options dictionary is carried around passes,
https://github.com/Qiskit/qiskit-terra/blob/924702e9ddb3f6f0124bc8acb285ac3d1da12aff/qiskit/transpiler/runningpassmanager.py#L153
but eventually no one use this information (at least in Terra passes). However, I cannot decide what should be removed. I also want to cleanup and drop un-used features. Let's discuss carefully in #10127 . Once this is merged I'll rebase the PR for easier review.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure it's ok, as long as it doesn't fall through the cracks. Btw. I think one or two people wrote or told me that preserves
was an idea copied from llvm without knowing whether it would be useful.
qiskit/transpiler/basepasses.py
Outdated
Enforces the creation of some fields in the pass while allowing passes to | ||
override ``__init__``. | ||
""" | ||
from qiskit.passmanager.base_pass import BasePass as CommonBasePass |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This means we have both passmanager.BasePass
and transpiler.basepasses.BasePass
. This will likely cause a little confusion when searching for things in the source tree. But, probably a good IDE would help. Also, in cases like this, people argue that this is exactly why namespaces exist. I think leaving this as you have it might not be a bad choice, but i'ts worth considering changing it. If I had a good substitute name, I'd suggest it. I think using passmanager.CommonBasePass
might make the passmanager
module too verbose.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's fair point. Since we have another cleanup PR #10127 , we can also change the class name in that PR if we come up with better substitute name. I would prefer changing the transpiler.basepasses.BasePass
to CircuitBasePass
and adding an alias of BasePass = CircuitBasePass
. Although this is a public class, the base class is immediately subclassed by transform and analysis pass. I assume impact to users is limited.
(edit)
In current implementation probably we can also assume BasePass
is agnostic to IR because .run
is abstractmethod and pass subclass must implement functionality based on expected IR. Adding typecheck to BasePass
is probably overkill. In this case we can just
from qiskit.passmanager.base_pass import BasePass
but we also need to move __call__
to passmanager.BasePass
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CircuitBasePass
. yes this is a good idea.
See also a previous PR #9163 that was closed in favor of this one. |
729b174
to
cb19359
Compare
Co-authored-by: Matthew Treinish <mtreinish@kortar.org>
Co-authored-by: Matthew Treinish <mtreinish@kortar.org> Co-authored-by: John Lapeyre <jlapeyre@users.noreply.github.com>
cb19359
to
ba6e698
Compare
Thanks @jlapeyre for approval. After discussion I came up with another name GenericPass. The
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/generic-classes |
LGTM, thanks for all the updates. Lets continue the review of the specific internals of the passmanager in #10127 |
This reverts commit fbd64d9.
This reverts commit fbd64d9. The follow on PR to this one Qiskit#10127 which is making internal refactors to the pass manager code now that's it a standalone module is still undergoing active review and the scope of the PR is sufficiently large that it likely won't be viable for the pending 0.25.0 release. This commit temporarily reverts Qiskit#10124 which was the first step of creating a module by porting the pass manager code in it's current form to a standalone module so that we're not committed to the API as part of the 0.25.0 release to give more time for Qiskit#10127 to finalize what the eventual `qiskit.passmanager` API will look like. This revert should itself be reverted after 0.25.0rc1 is tagged and the main branch opens up for 0.45.0 development. As this revert is not an indication that we did not want Qiskit#10124 it's just to avoid committing to the API prematurely.
…10454) This reverts commit fbd64d9. The follow on PR to this one #10127 which is making internal refactors to the pass manager code now that's it a standalone module is still undergoing active review and the scope of the PR is sufficiently large that it likely won't be viable for the pending 0.25.0 release. This commit temporarily reverts #10124 which was the first step of creating a module by porting the pass manager code in it's current form to a standalone module so that we're not committed to the API as part of the 0.25.0 release to give more time for #10127 to finalize what the eventual `qiskit.passmanager` API will look like. This revert should itself be reverted after 0.25.0rc1 is tagged and the main branch opens up for 0.45.0 development. As this revert is not an indication that we did not want #10124 it's just to avoid committing to the API prematurely.
…" (Qiskit#10454) This reverts commit fbd64d9. The follow on PR to this one Qiskit#10127 which is making internal refactors to the pass manager code now that's it a standalone module is still undergoing active review and the scope of the PR is sufficiently large that it likely won't be viable for the pending 0.25.0 release. This commit temporarily reverts Qiskit#10124 which was the first step of creating a module by porting the pass manager code in it's current form to a standalone module so that we're not committed to the API as part of the 0.25.0 release to give more time for Qiskit#10127 to finalize what the eventual `qiskit.passmanager` API will look like. This revert should itself be reverted after 0.25.0rc1 is tagged and the main branch opens up for 0.45.0 development. As this revert is not an indication that we did not want Qiskit#10124 it's just to avoid committing to the API prematurely.
…kit#10124)" (Qiskit#10454)" (Qiskit#10474) This reverts commit c03e4c7.
Summary
This PR adds new
qiskit.passmanager
module and reorganizesqiskit.transpiler
. New module implements a generic pass manager which is not sensitive to object types (input, output, IR) under transformation, and only provides a management for pass execution.1 of 2 PRs. Pass manager internals will be refactored in the follow up.
Details and comments
The internal logic is almost as-is. One visible change is in
qiskit.passmanager.passrunner
. This providesBasePassRunner
which is a superclass ofRunningPassManager
. New base class implementsBasePassRunner._to_passmanager_ir
BasePassRunner._to_target
BasePassRunner._run_base_pass
which are all abstract methods. These are type sensitive and intended to be implemented by a subclass for particular data types, e.g. for existing pass manager, input: QuantumCircuit, passmanager_ir: DAGCircuit, output: QuantumCircuit. We plan to introduce another compiler for the pulse module.
The new methods
BasePassRunner._run_pass_generic
implements data type agnostic flow control. This is a common machinery for every subclass.