Qiskit / qiskit

Qiskit is an open-source SDK for working with quantum computers at the level of extended quantum circuits, operators, and primitives.
https://www.ibm.com/quantum/qiskit
Apache License 2.0
5.11k stars 2.34k forks source link

Fully port Split2QUnitaries to rust #13025

Closed mtreinish closed 3 weeks ago

mtreinish commented 1 month ago

Summary

This commit builds off of #13013 and the other data model in Rust infrastructure and migrates the InverseCancellation pass to operate fully in Rust. The full path of the transpiler pass now never leaves Rust until it has finished modifying the DAGCircuit. There is still some python interaction necessary to handle parts of the data model that are still in Python, mainly for creating UnitaryGate instances and ParameterExpression for global phase. But otherwise the entirety of the pass operates in rust now.

This is just a first pass at the migration here, it moves the pass to use loops in rust. The next steps here are to look at operating the pass in parallel. There is no data dependency between the optimizations being done for different gates so we should be able to increase the throughput of the pass by leveraging multithreading to handle each gate in parallel. This commit does not attempt this though, because of the Python dependency and also the data structures around gates and the dag aren't really setup for multithreading yet and there likely will need to be some work to support that.

Details and comments

~This PR is based on top of https://github.com/Qiskit/qiskit/pull/13013 and as such github shows the entire contents of https://github.com/Qiskit/qiskit/pull/13013 in addition to the contents of this PR. To see the contents of this PR you can look at HEAD on this branch, or just look at: https://github.com/Qiskit/qiskit/pull/13025/commits/0689b736d9f5d49427f07fb6950e5416aedf861d~ Rebased

Part of #12208

qiskit-bot commented 1 month ago

One or more of the following people are relevant to this code:

coveralls commented 1 month ago

Pull Request Test Coverage Report for Build 10772500080

Details


Changes Missing Coverage Covered Lines Changed/Added Lines %
crates/accelerate/src/split_2q_unitaries.rs 42 44 95.45%
crates/circuit/src/dag_circuit.rs 49 55 89.09%
<!-- Total: 98 106 92.45% -->
Files with Coverage Reduction New Missed Lines %
crates/qasm2/src/lex.rs 7 91.73%
<!-- Total: 7 -->
Totals Coverage Status
Change from base Build 10770445393: 0.01%
Covered Lines: 73022
Relevant Lines: 81897

💛 - Coveralls
mtreinish commented 3 weeks ago

For benchmarks I didn't do anything too extensive. But I ran this script:

import statistics
import time

from qiskit.circuit.random import random_circuit
from qiskit.transpiler.passes import ConsolidateBlocks, Split2QUnitaries

split_pass = Split2QUnitaries()

times = []
for _ in range(100):
    qc = random_circuit(100, 1000)
    blocked = ConsolidateBlocks()(qc)
    start = time.perf_counter()
    split_pass(blocked)
    stop = time.perf_counter()
    runtime = stop - start
    print(runtime)
    times.append(runtime)

mean_runtime = statistics.geometric_mean(times)
print(f"Mean runtime over 100x 100x1000 random circuits: {mean_runtime} sec.")

with both main and this PR. With main it returned:

Mean runtime over 100x 100x1000 random circuits: 0.22658202673859693 sec.

With this PR it yielded:

Mean runtime over 100x 100x1000 random circuits: 0.15633993219475464 sec.

It's not as much of as speedup as I was hoping for, but still pretty good. Also, this isn't a perfect comparison because it does include the circuit -> dag overhead also I have no idea how many substitutions are actually getting made by this.

sbrandhsn commented 3 weeks ago

I have no idea how many substitutions are actually getting made by this.

Probably close to zero, which is the expected case for a reasonable circuit. :-) I think a lot of users would be willing to pay a lot of classical compute if they can save one two-qubit gate without introducing further errors.

mtreinish commented 3 weeks ago

Lol, it's actually zero because I forgot to unroll 3q or more and also the collect blocks pass, so there are no collected unitaries in the circuit. I'll fix it and rerun the script.