Skip to content

Conversation

mtreinish
Copy link
Member

Summary

This commit updates the det() function used for computing the determinant of the unitary used as part of the calculation of one and two qubit unitary deocmposers. It is now using the numpy linalg module's det() function. Previously it was using the function from scipy which required a runtime import and also marginally slower under cProfile (which might be a red herring because of profiler overhead as scipy has more python space calls). This also standardizes the det() call usage in the module as other places were already using the numpy version of the function.

Details and comments

This commit updates the det() function used for computing the determinant
of the unitary used as part of the calculation of one and two qubit
unitary deocmposers. It is now using the numpy linalg module's det()
function. Previously it was using the function from scipy which required
a runtime import and also marginally slower under cProfile (which might
be a red herring because of profiler overhead as scipy has more python
space calls). This also standardizes the det() call usage in the module
as other places were already using the numpy version of the function.
@mtreinish mtreinish added performance mod: quantum info Related to the Quantum Info module (States & Operators) Changelog: None Do not include in changelog labels Nov 22, 2022
@qiskit-bot
Copy link
Collaborator

Thank you for opening a new pull request.

Before your PR can be merged it will first need to pass continuous integration tests and be reviewed. Sometimes the review process can be slow, so please be patient.

While you're waiting, please feel free to review other open PRs. While only a subset of people are authorized to approve pull requests for merging, everyone is encouraged to review open pull requests. Doing reviews helps reduce the burden on the core team and helps make the project's code better for everyone.

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

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.

At least historically, the recommendation was to use scipy.linalg instead of numpy.linalg because Scipy would guarantee that all its methods were built against some BLAS/LAPACK implementation, whereas Numpy would sometimes use custom fallbacks if it didn't have BLAS/LAPACK available at build. I don't really know what the status of that is any more (my knowledge is about 5 years old at this point) - the Scipy documentation still spouts the same reasoning, but I don't really know if it's up-to-date.

That aside, in principle this swap seems acceptable to me.

@coveralls
Copy link

Pull Request Test Coverage Report for Build 3524760087

  • 4 of 4 (100.0%) changed or added relevant lines in 2 files are covered.
  • 1 unchanged line in 1 file lost coverage.
  • Overall coverage decreased (-0.002%) to 84.603%

Files with Coverage Reduction New Missed Lines %
qiskit/circuit/tools/pi_check.py 1 91.23%
Totals Coverage Status
Change from base Build 3517604750: -0.002%
Covered Lines: 62762
Relevant Lines: 74184

💛 - Coveralls

@mtreinish
Copy link
Member Author

mtreinish commented Nov 22, 2022

I guess I could see that as being a potential pitfall. At least on our supported platforms there are numpy wheels available (except ppc64le and s390x) which include openblas afaik. Looking through the numpy repo there is still a lapack_lite package: https://github.com/numpy/numpy/tree/c8dd91b633798a4082f255784dec483b08351f58/numpy/linalg/lapack_lite which I guess is the fallback they're referring to. I will say in the past we've switched from scipy to numpy because the default LAPACK driver that scipy uses for eigh() was problematic for consistent results (see: #5251 and #5263 ).

In this case though I'm not sure there is really any harm we were already using a mix of numpy and scipy's det() function and I just was unifying on the numpy one to avoid the runtime import.

@jakelishman
Copy link
Member

Yeah, eigh used to give us no end of trouble on QuTiP as well. I'm happy just to merge this to unify things - as you say, there's less Python overhead with Numpy, and for such small matrices, I suspect there's nothing much to be gained from a good LAPACK anyway.

I'm happy just to merge this.

@mergify mergify bot merged commit 30ee992 into Qiskit:main Nov 22, 2022
@mtreinish mtreinish deleted the np-det-func branch November 22, 2022 17:55
mtreinish added a commit to mtreinish/qiskit-core that referenced this pull request Nov 22, 2022
This commit ports the per basis parameter calculation from python to
rust. In looking at the runtime performance regression caused by Qiskit#8917
the majority is just that we're doing more work synthesizing to more
available basis to potentially produce better quality results. Profiling
the transpiler pass shows we're spending a non-trivial amount of time in
numpy/scipy (depending on whether it's before or after Qiskit#9179) computing
the determinant of the unitary. This is likely because those determinant
functions are designed to work with an arbitrarily large square matrix
while for the 1 qubit decomposer we're only ever working with a 2x2.
To remove this overhead this commit writes a dedicated rust function to
compute the determinant of a 2x2 complex matrix and then also adds
dedicated functions to calculate the angles for given basis to rust
as we can easily just return the end result from rust.

Related Qiskit#8774
mtreinish added a commit to mtreinish/qiskit-core that referenced this pull request Nov 22, 2022
This commit ports the per basis parameter calculation from python to
rust. In looking at the runtime performance regression caused by Qiskit#8917
the majority is just that we're doing more work synthesizing to more
available basis to potentially produce better quality results. Profiling
the transpiler pass shows we're spending a non-trivial amount of time in
numpy/scipy (depending on whether it's before or after Qiskit#9179) computing
the determinant of the unitary. This is likely because those determinant
functions are designed to work with an arbitrarily large square matrix
while for the 1 qubit decomposer we're only ever working with a 2x2.
To remove this overhead this commit writes a dedicated rust function to
compute the determinant of a 2x2 complex matrix and then also adds
dedicated functions to calculate the angles for given basis to rust
as we can easily just return the end result from rust.

Related Qiskit#8774
mergify bot pushed a commit that referenced this pull request Dec 2, 2022
* Oxidize parameter calculation for OneQubitEulerDecomposer

This commit ports the per basis parameter calculation from python to
rust. In looking at the runtime performance regression caused by #8917
the majority is just that we're doing more work synthesizing to more
available basis to potentially produce better quality results. Profiling
the transpiler pass shows we're spending a non-trivial amount of time in
numpy/scipy (depending on whether it's before or after #9179) computing
the determinant of the unitary. This is likely because those determinant
functions are designed to work with an arbitrarily large square matrix
while for the 1 qubit decomposer we're only ever working with a 2x2.
To remove this overhead this commit writes a dedicated rust function to
compute the determinant of a 2x2 complex matrix and then also adds
dedicated functions to calculate the angles for given basis to rust
as we can easily just return the end result from rust.

Related #8774

* Eliminate python function for staticmethod definition

This commit removes one layer of function calls for the
OneQubitEulerDecomposer's staticmethods for calculating parameters.
Previously, there was a python function which called an inner rust
function, this eliminates one layer and attaches the rust function
directly as a static method to the class definition.
Cryoris pushed a commit to Cryoris/qiskit-terra that referenced this pull request Jan 12, 2023
This commit updates the det() function used for computing the determinant
of the unitary used as part of the calculation of one and two qubit
unitary deocmposers. It is now using the numpy linalg module's det()
function. Previously it was using the function from scipy which required
a runtime import and also marginally slower under cProfile (which might
be a red herring because of profiler overhead as scipy has more python
space calls). This also standardizes the det() call usage in the module
as other places were already using the numpy version of the function.
Cryoris pushed a commit to Cryoris/qiskit-terra that referenced this pull request Jan 12, 2023
* Oxidize parameter calculation for OneQubitEulerDecomposer

This commit ports the per basis parameter calculation from python to
rust. In looking at the runtime performance regression caused by Qiskit#8917
the majority is just that we're doing more work synthesizing to more
available basis to potentially produce better quality results. Profiling
the transpiler pass shows we're spending a non-trivial amount of time in
numpy/scipy (depending on whether it's before or after Qiskit#9179) computing
the determinant of the unitary. This is likely because those determinant
functions are designed to work with an arbitrarily large square matrix
while for the 1 qubit decomposer we're only ever working with a 2x2.
To remove this overhead this commit writes a dedicated rust function to
compute the determinant of a 2x2 complex matrix and then also adds
dedicated functions to calculate the angles for given basis to rust
as we can easily just return the end result from rust.

Related Qiskit#8774

* Eliminate python function for staticmethod definition

This commit removes one layer of function calls for the
OneQubitEulerDecomposer's staticmethods for calculating parameters.
Previously, there was a python function which called an inner rust
function, this eliminates one layer and attaches the rust function
directly as a static method to the class definition.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Changelog: None Do not include in changelog mod: quantum info Related to the Quantum Info module (States & Operators) performance
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants