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

Performance improvements for collect_2q_blocks #6433

Merged
merged 22 commits into from
Jun 8, 2021

Conversation

IvanIsCoding
Copy link
Contributor

@IvanIsCoding IvanIsCoding commented May 18, 2021

Summary

Closes Qiskit/rustworkx#265

This PR contains two core improvements that boost the performance of collect_2q_blocks:

  • Use new functions from retworkx in quantum_successors and quantum_predecessors that are more efficient
  • Add is_successor and is_predecessor function to DAGCircuit to efficiently check for successors/predecessors instead of getting all successors/predecessors and then doing a check

It also contains two minor performance optimizations that are open to debate:

  • Replace qargs with _qargs, because of @property overhead when getting qargs
  • Replace op with _op, idem

Details and comments

This PR also upgrades retworkx to version 0.9

@IvanIsCoding IvanIsCoding requested a review from a team as a code owner May 18, 2021 09:01
@IvanIsCoding
Copy link
Contributor Author

IvanIsCoding commented May 18, 2021

I benchmarked the changes and I got results ranging from 1.3x to 1.5x times faster.

Below is the code for one of the benchmarks. It is a Quantum Volume Circuit, unrolled to use cx and u3 gates. I got a 1.45x speedup on the transpiler pass on that circuit.

import timeit
from qiskit import QuantumRegister, QuantumCircuit
from qiskit.circuit.library import QuantumVolume
from qiskit.converters import circuit_to_dag
from qiskit.transpiler.passes.optimization import Collect2qBlocks
from qiskit.compiler import transpile

N = 100
q = QuantumRegister(N, 'q')
qc = QuantumCircuit(q)
qc.append(
	QuantumVolume(N, N//2, seed=2, classical_permutation=False), q
)

qc = transpile(qc, optimization_level=0, basis_gates=['u1', 'u2', 'u3', 'cx'])
dag = circuit_to_dag(qc)
c2q = Collect2qBlocks()

print(
	timeit.timeit("c2q.run(dag)", globals=globals(), number=10)
)

Time without optimizations: 3.6710015139997267
Time with optimizations: 2.5208510480006225

requirements.txt Outdated Show resolved Hide resolved
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.

Can you add an upgrade release note here about the bump in the minimum required retworkx version. We should call that out in the release notes as a thing that might require end user manual updates when upgrading to the next terra release.

@IvanIsCoding IvanIsCoding changed the title [WIP] Performance improvements for collect_2q_blocks Performance improvements for collect_2q_blocks Jun 1, 2021
@IvanIsCoding
Copy link
Contributor Author

Can you add an upgrade release note here about the bump in the minimum required retworkx version. We should call that out in the release notes as a thing that might require end user manual updates when upgrading to the next terra release.

I added the release note. This is no longer WIP, it can be merged

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.

LGTM, just one comment with some suggestions on the release notes. Other than that I think this is ready to go.

releasenotes/notes/bump-retworkx-59c7ab59ad02c3c0.yaml Outdated Show resolved Hide resolved
@mtreinish
Copy link
Member

mtreinish commented Jun 2, 2021

I also ran the asv collect_2q_blocks benchmark on this and it yielded this result:

Benchmarks that have improved:

       before           after         ratio
     [a2193a5c]       [e2935d73]
     <main>       <IvanIsCoding-improve_collect2q>
-      44.3±0.2ms       30.4±0.2ms     0.69  passes.PassBenchmarks.time_collect_2q_blocks(14, 1024)
-      65.8±0.3ms       44.9±0.6ms     0.68  passes.PassBenchmarks.time_collect_2q_blocks(20, 1024)
-      15.4±0.1ms       10.3±0.3ms     0.67  passes.PassBenchmarks.time_collect_2q_blocks(5, 1024)

SOME BENCHMARKS HAVE CHANGED SIGNIFICANTLY.
PERFORMANCE INCREASED.

@mtreinish
Copy link
Member

I also ran a quick benchmark on https://github.com/Qiskit/qiskit/blob/master/test/benchmarks/qasm/test_eoh_qasm.qasm (which is different load on the pass because it's all 2q, so one giant block) with:

import time
import statistics

from qiskit.transpiler.passes import Collect2qBlocks
from qiskit.circuit import QuantumCircuit
from qiskit.converters import circuit_to_dag

qc = QuantumCircuit.from_qasm_file('test_eoh_qasm.qasm')
dag = circuit_to_dag(qc)
collect_pass = Collect2qBlocks()
times = []
for i in range(20):
    start = time.time()
    collect_pass.run(dag)
    stop = time.time()
    times.append(stop - start)
print("Mean run time: %s" % statistics.mean(times))

which returns 0.015 seconds on main and 0.01 seconds with this PR.

@IvanIsCoding
Copy link
Contributor Author

I commited the suggestions to the release note, the need for retworkx upgrade should be clearer now

I also ran the asv collect_2q_blocks benchmark on this and it yielded this result:

Benchmarks that have improved:

       before           after         ratio
     [a2193a5c]       [e2935d73]
     <main>       <IvanIsCoding-improve_collect2q>
-      44.3±0.2ms       30.4±0.2ms     0.69  passes.PassBenchmarks.time_collect_2q_blocks(14, 1024)
-      65.8±0.3ms       44.9±0.6ms     0.68  passes.PassBenchmarks.time_collect_2q_blocks(20, 1024)
-      15.4±0.1ms       10.3±0.3ms     0.67  passes.PassBenchmarks.time_collect_2q_blocks(5, 1024)

SOME BENCHMARKS HAVE CHANGED SIGNIFICANTLY.
PERFORMANCE INCREASED.

Cool, the 1.3x - 1.5x speed up remained consistent accross the benchmarks.

mtreinish
mtreinish previously approved these changes Jun 2, 2021
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.

Oops, thanks for fixing the whitespace issue in my release note suggestion (sigh getting whitespace right in the github editor is so irritating).

@mtreinish mtreinish added automerge Changelog: None Do not include in changelog labels Jun 7, 2021
@mergify mergify bot merged commit 0240377 into Qiskit:main Jun 8, 2021
@IvanIsCoding IvanIsCoding deleted the improve_collect2q branch July 14, 2022 05:36
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.

Port collect 2q blocks function from qiskit-terra
2 participants