Skip to content

Conversation

mtreinish
Copy link
Member

@mtreinish mtreinish commented Feb 26, 2021

Summary

This commit improves the performance slightly of the
OneQubitEulerDecomposer by making to changes, avoiding the use of
append() and avoiding the use of np.isclose().

Avoiding append(), which does extra validation of the arguments when
constructing the output circuits. Instead the _append() method is used
which does not have the validation overhead, however this is not
necessary since we know how the circuit is constructed and the
arguments when adding the gate are being set correctly (there is only
1 qubit anyway).

The np.isclose() function quickly becomes a bottlneck in the
OneQubitEulerDecomposer class as the majority of the operations are
comparing angles to decide when to insert gates. However, we can avoid
this overhead by switching from numpy's isclose function which is
optimized for arrays not floats [1][2] to just using the standard
library's math module's isclose() function. This commit makes this
change as well as using intermediate variables to avoid duplicate
calculations to speed up the decomposer.

Details and comments

[1] numpy/numpy#16160
[2] numpy/numpy#10161

This commit improves the performance slightly of the
OneQubitEulerDecomposer by avoiding the use of append(), which does extra
validation of the arguments when constructing the output circuits.
Instead the _append() method is used which does not have the validation
overhead, however this is not necessary since we know how the circuit is
constructed and the arguments when adding the gate are being set
correctly (there is only 1 qubit anyway).
The np.isclose() function quickly becomes a bottlneck in the
OneQubitEulerDecomposer class as the majority of the operations are
comparing angles to decide when to insert gates. However, we can avoid
this overhead by switching from numpy's isclose function which is
optimzed for arrays not floats [1][2] to just using the standard
library's math module's isclose() function. This commit makes this
change as well as using intermediate variables to avoid duplicate
calculations to speed up the decomposer.
@mtreinish mtreinish changed the title Remove append() overhead from OneQubitEulerDecomposer Tune performance of OneQubitEulerDecomposer Feb 27, 2021
@mtreinish
Copy link
Member Author

mtreinish commented Feb 27, 2021

To see the difference here are profiles from running the decomposer as part of the 1q optimization pass as part of a transpile of a qv 7x7 model circuit. WIthout this PR:

Screenshot_2021-02-26_19-16-48

With this PR:

Screenshot_2021-02-26_19-22-24

The thing I'm not sure of right now is why _append() gets so much slower with this PR there shouldn't be any difference between the method before or after. (EDIT: I wonder if it's just cProfile overhead, it can make function calls seem much slower than reality)

@mtreinish
Copy link
Member Author

The other thing I think we should look at doing (although not in this PR) is adding support to the deocmposer for working in a DAGCircuit instead of a QuantumCircuit. That way for the one qubit decomposition pass we can have the decomposer natively construct a dag that can be substituted in directly. The conversion circuit-> dag conversion is a small component performance wise, but it might be slightly faster to work in the dag natively than in a circuit.

According to the np.mod() docs [1] the np.mod() is equivalent to the
stdlib '%' operator in python however it is designed to work with numpy
array's instead of single values. This adds about an order of magnitude
overhead to the mod operations (on the order of 1us vs 100ns) which can
add up as _mod2pi is called multiple times. However python's mod
operator is not ideal for working with floats [2] and when used produces
different results than expected. To avoid this but still improve
performance this commit switches to use the stdlib math module's
fmod() function, which produces the expected result and is only
marginaly slower than the '%' operator, which will still avoid the
overhead of the numpy function.

[1] https://numpy.org/doc/stable/reference/generated/numpy.mod.html
[2] https://docs.python.org/3/library/math.html#math.fmod
@mtreinish mtreinish added this to the 0.17 milestone Feb 27, 2021
@mergify mergify bot merged commit 9019cfa into Qiskit:master Mar 5, 2021
@mtreinish mtreinish deleted the tune-euler-decompose branch March 5, 2021 18:25
@kdk kdk added the Changelog: None Do not include in changelog label Mar 31, 2021
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 performance
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants