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

Pass manager refactoring: add passmanager module #10124

Merged

Conversation

nkanazawa1989
Copy link
Contributor

Summary

This PR adds new qiskit.passmanager module and reorganizes qiskit.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 provides BasePassRunner which is a superclass of RunningPassManager. New base class implements

  • BasePassRunner._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.

@nkanazawa1989 nkanazawa1989 requested a review from a team as a code owner May 17, 2023 13:49
@qiskit-bot
Copy link
Collaborator

One or more of the the following people are requested to review this:

@nkanazawa1989 nkanazawa1989 added Changelog: New Feature Include in the "Added" section of the changelog mod: transpiler Issues and PRs related to Transpiler labels May 17, 2023
@nkanazawa1989 nkanazawa1989 added this to the 0.25.0 milestone May 17, 2023
@nkanazawa1989 nkanazawa1989 force-pushed the feature/passmanager-refactoring-pr1 branch from ddb834c to bd93d94 Compare May 17, 2023 14:03
@mtreinish mtreinish self-assigned this May 17, 2023
@nkanazawa1989 nkanazawa1989 mentioned this pull request May 17, 2023
3 tasks
@coveralls
Copy link

coveralls commented May 17, 2023

Pull Request Test Coverage Report for Build 5352619334

  • 389 of 413 (94.19%) changed or added relevant lines in 13 files are covered.
  • 21 unchanged lines in 6 files lost coverage.
  • Overall coverage increased (+0.003%) to 85.947%

Changes Missing Coverage Covered Lines Changed/Added Lines %
qiskit/passmanager/base_pass.py 40 41 97.56%
qiskit/transpiler/runningpassmanager.py 55 57 96.49%
qiskit/passmanager/passmanager.py 89 95 93.68%
qiskit/passmanager/passrunner.py 76 83 91.57%
qiskit/passmanager/flow_controllers.py 63 71 88.73%
Files with Coverage Reduction New Missed Lines %
crates/qasm2/src/expr.rs 1 93.76%
qiskit/transpiler/passes/synthesis/unitary_synthesis.py 1 90.39%
crates/qasm2/src/lex.rs 2 90.89%
qiskit/extensions/quantum_initializer/squ.py 2 80.0%
crates/accelerate/src/vf2_layout.rs 3 94.74%
crates/qasm2/src/parse.rs 12 96.65%
Totals Coverage Status
Change from base Build 5334907613: 0.003%
Covered Lines: 71473
Relevant Lines: 83159

💛 - Coveralls

@nkanazawa1989 nkanazawa1989 force-pushed the feature/passmanager-refactoring-pr1 branch 2 times, most recently from 61cfff8 to 8261a66 Compare May 18, 2023 17:12
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.

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.

qiskit/passmanager/__init__.py Outdated Show resolved Hide resolved
qiskit/passmanager/__init__.py Outdated Show resolved Hide resolved
qiskit/passmanager/__init__.py Outdated Show resolved Hide resolved
qiskit/passmanager/__init__.py Outdated Show resolved Hide resolved
qiskit/passmanager/propertyset.py Show resolved Hide resolved
qiskit/transpiler/passmanager.py Show resolved Hide resolved
qiskit/passmanager/passmanager.py Outdated Show resolved Hide resolved
logger = logging.getLogger(__name__)


class BasePassManager(ABC):
Copy link
Member

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.

Copy link
Contributor Author

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

qiskit/transpiler/passmanager.py Outdated Show resolved Hide resolved
qiskit/transpiler/passmanager.py Outdated Show resolved Hide resolved
@nkanazawa1989 nkanazawa1989 force-pushed the feature/passmanager-refactoring-pr1 branch from 7e9d4b3 to 729b174 Compare June 7, 2023 15:59
mtreinish
mtreinish previously approved these changes Jun 14, 2023
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.

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

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.

Copy link
Contributor

@jlapeyre jlapeyre left a 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
Copy link
Contributor

@jlapeyre jlapeyre Jun 15, 2023

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?

Copy link
Member

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

Copy link
Contributor Author

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.

Copy link
Contributor

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.

Enforces the creation of some fields in the pass while allowing passes to
override ``__init__``.
"""
from qiskit.passmanager.base_pass import BasePass as CommonBasePass
Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Contributor

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.

@jlapeyre jlapeyre self-assigned this Jun 15, 2023
@jlapeyre
Copy link
Contributor

See also a previous PR #9163 that was closed in favor of this one.

@nkanazawa1989 nkanazawa1989 force-pushed the feature/passmanager-refactoring-pr1 branch from 729b174 to cb19359 Compare June 23, 2023 02:06
nkanazawa1989 and others added 4 commits June 23, 2023 11:59
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>
@nkanazawa1989 nkanazawa1989 force-pushed the feature/passmanager-refactoring-pr1 branch from cb19359 to ba6e698 Compare June 23, 2023 03:01
@nkanazawa1989
Copy link
Contributor Author

Thanks for the review. I just updated document in ba6e698 and rebased this PR. @jlapeyre Let's discuss BasePass naming and removal of unused feature in the followup PR #10127 .

jlapeyre
jlapeyre previously approved these changes Jun 23, 2023
@nkanazawa1989
Copy link
Contributor Author

Thanks @jlapeyre for approval. After discussion I came up with another name GenericPass. The passmanager.base_pass.GenericPass (BasePass) doesn't implement any feature specific to a particular IR / transformation, and this make me think this is sort of generic class.

Generic classes encapsulate operations that are not specific to a particular data type. The most common use for generic classes is with collections like linked lists, hash tables, stacks, queues, trees, and so on. Operations such as adding and removing items from the collection are performed in basically the same way regardless of the type of data being stored.

https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/generic-classes

@mtreinish
Copy link
Member

LGTM, thanks for all the updates. Lets continue the review of the specific internals of the passmanager in #10127

@mtreinish mtreinish added this pull request to the merge queue Jun 23, 2023
Merged via the queue into Qiskit:main with commit fbd64d9 Jun 23, 2023
14 checks passed
mtreinish added a commit that referenced this pull request Jul 20, 2023
mtreinish added a commit to mtreinish/qiskit-core that referenced this pull request Jul 20, 2023
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.
github-merge-queue bot pushed a commit that referenced this pull request Jul 20, 2023
…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.
mtreinish added a commit that referenced this pull request Jul 21, 2023
github-merge-queue bot pushed a commit that referenced this pull request Jul 22, 2023
to24toro pushed a commit to to24toro/qiskit-terra that referenced this pull request Aug 3, 2023
…" (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.
to24toro pushed a commit to to24toro/qiskit-terra that referenced this pull request Aug 3, 2023
@nkanazawa1989 nkanazawa1989 deleted the feature/passmanager-refactoring-pr1 branch December 11, 2023 16:23
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 priority: high
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants