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
4.84k stars 2.29k forks source link

More lightweight gate append method #12509

Open nkanazawa1989 opened 1 month ago

nkanazawa1989 commented 1 month ago

What should we add?

When I write a very long circuit that includes tons of Rz gate, the _update_parameter_table called from here dominates the circuit construction time.

https://github.com/Qiskit/qiskit/blob/797bb285632a4b58c35c9e4cf5be44502b5bd78a/qiskit/circuit/quantumcircuit.py#L2461

This implementation is annoying in two scenarios.

nkanazawa1989 commented 1 month ago

With the same circuit with #12508 (this is the first scenario -- fixed angles but ~10k RZGates), this _track_operation is the most dominant overhead while it does nothing (just repeats tons of isinstance check for my bound parameters).

image

mtreinish commented 1 month ago

Can you test this with #12459 , which rewrites all of this code and adds a fast path for adding standard gates. We still always need to do an isinstance call on each parameter to determine which ones are a ParameterExpression and which are a float type so that we can update the parameter table for unbound parameters. That can't changed but I expect most of the slowdown you're seeing will be addressed by that for standard gates (custom defined gates are a different story though).

mtreinish commented 1 month ago

That being said the expert mode I suggested after #12459 in #12508 will also work here. Passing a CircuitInstruction to _append directly will minimize the overhead (despite the underscore _append is a public method, it's just not for general use).

nkanazawa1989 commented 1 month ago

Thanks Matthew. I tried your PR branch. The branch was installed by python setup.py install

(main) image

The parameter table update check is the significant overhead, which is not necessary at all in my use case.

(your branch, same code, i.e. _append) image

Unfortunately it becomes slower because I don't use StandardGate enum (imported from the standard_gates module).

(your branch, modified code to use _append_standard_gate) image

Even slower. I don't know why since I don't scrutinize your code.

nkanazawa1989 commented 1 month ago

Doing below on your PR branch drastically improves the performance.

my_circuit._data.append(CircuitInstruction(StandardGate.RZGate, params=params, qubits=qubits))

With the same setting: image

I really like this hack. Hope this will be available to everyone soon.