-
Notifications
You must be signed in to change notification settings - Fork 2.4k
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
Add pulse gate pass #6759
Add pulse gate pass #6759
Conversation
Thanks @eggerdj for the reviewing. I think this pass is necessary for all optimization levels, because calibration update and circuit optimization are separate context. For example, user should be able to create custom x gate, and use that gate with every optimization levels. Basically this is the same as writing : non_opt_circ = QuantumCircuit(nq)
...
non_opt_circ.add_calibration("x", (0,), schedule=x_gate)
opt0 = transpile(non_opt_circ, backend, optimization_level=0)
opt1 = transpile(non_opt_circ, backend, optimization_level=1)
opt2 = transpile(non_opt_circ, backend, optimization_level=2)
opt3 = transpile(non_opt_circ, backend, optimization_level=3) however here we want to avoid explicitly writing |
There are two things that make me feel a bit uneasy about this approach: 1- The idea of changing from qiskit.transpiler import InstructionDurations
durations = InstructionDurations.from_backend(backend)
durations.update('cx', (0, 1), 200, 'ns')
transpile(circ, backend, durations) # this will over-ride the backend's durations 2- Is it really a big deal to write |
Thanks Ali for the comments :)
I don't remember where I saw this, but if I recall correctly
According to this API docs,
so overriding backend defaults is not quite unexpected usage. Actually, almost all members of
Yes. With above code example it's not quite easy to understand the benefit of this implementation (you can still write Let's assume following workflow. Here we want to calibrate SX gate and evaluate this with randomized benchmarking. Please compare the pseudo codes below. in current workflow
what this PR proposes
The RB is a part of experiment so we can implement some calibration attachment logic in experiment. However, once we try to use calibrated gate for other expeirment, i.e. we may want to calibrate custom basis gates, such as CCR gate that implements iSWAP, and we may want use this for VQE. However, in this case, we need to write the hook shown in above example. This is really hurts user experience. (edited) |
As commented in #6825 I think this approach is fine. This is a bit of me thinking out loud: I don't quite like this process of discovering which cals are supplied by the backend and which cals are supplied by the user seems a bit hacky (relying on 'metadata'). If I understand correctly you are doing this to attach user cals to the payload (
This is a bit arbitrary IMO. We could even go one level higher and ask backend compiler do more compilation --- so we can even send a circuit with toffolis as payload (e.g. ionq does this). I think a better philosophy is to make the frontend compiler create the actual physical circuit, which inevitably means resolving timing and also attaching pulse definitions for all the gates. This type of payload is then consistent with qasm3 as well. So even though the backend advertises its gate cals, we still include the subset of cals relevant to our circuit in the payload. It is then very explicit what the payload is doing (even if someone inspects it outside of the context of the backend). |
I like the idea. Since usually backends don't define many kind of basis gates, the overhead of attaching all gate defs is not quite large. However this sounds like we need matrix-like configuration rather than current
because generation of lower layer target code (timing/gate-attached) may hurt simulator performance. This is rough idea, but we may still need to separate Anyhow unifying real backend execution pass to (2) seems to make the chain cleaner.
This is not true. In the instruction schedule map, pulse instructions are stored with assigned parameter because Another thing I don't quite understand is the behavior of backend compiler when calibration is attached to the circuit. If the compiler always recognizes the gate def entry as a custom pulse, it may duplicate the waveform data in the waveform memory, and eventually we could increase the risk of getting waveform memory overflow error. |
Simulator backends shouldn't have cals in them, so I don't think any cals get attached anyway.
Yeah definitely we should make those cals leverage parameterized pulses |
I would be ok with this for a "pulse-level" payload. We should not do this for all jobs (not sure if was being suggested) as:
I am not opposed to using the metadata for this purpose as you've done. Personally, I have no problem with Backends being treated as mutable compilation targets. In the long run, I think they should even store/configure the passes that they will apply during thranspilation. How do you determine whether to insert calibrations or not in transpile? Is there some option? |
Thanks Ali, Thomas, Sounds like these comments are somewhat conflicting:
Perhaps we need tell the transpiler the level of compilation? i.e.
If QASM3 code is generated per job we could serialize the instruction schedule map itself without attaching instructions to each circuit. In this case, how we can distinguish global
This is implicitly done by leveraging the metadata in current design. Because the inst map instance (attached to backend object) is populated with I think a backend object is self-contaiend and can override basis gate only by itself. |
This would require the ability to call defcals explicitly in the qasm3 and provide multiple calibration definitions for the same gate(which is planned). See openqasm/openqasm#244 |
I am ok with the metadata approach. Regarding multiple circuit classes, I would rather prefer to unify the circuit/pulse within one object structure (IR). We could have different canonical phases/forms within this IR structure to denote the format at the current point in compilation (eg., mapped, scheduled, calibrated, etc.). |
…librations_pass # Conflicts: # qiskit/compiler/transpiler.py # qiskit/transpiler/passes/scheduling/calibration_creators.py
…librations_pass # Conflicts: # test/python/pulse/test_instruction_schedule_map.py
…qiskit-terra into feature/calibrations_pass
Co-authored-by: Thomas Alexander <[email protected]>
Co-authored-by: Thomas Alexander <[email protected]>
Co-authored-by: Thomas Alexander <[email protected]>
Co-authored-by: Thomas Alexander <[email protected]>
…qiskit-terra into feature/calibrations_pass
Summary
This PR improves handling of pulse gates.
Current work flow
With new pass
This may benefit the calibration framework in Qiskit Experiment.
Details and comments
The simple trick enabling this workflow is the schedule metadata "publisher" (name TBD, welcome suggestions). Note that schedules in the instmap that are provided by the backend are always registered by
PulseDefaults
constructor. This PR adds the publisher metadata of backend to the schedule registered by this.https://github.com/Qiskit/qiskit-terra/blob/9b48476cbaf5c4742f67e1ff6ce2546ba5fad01f/qiskit/providers/models/pulsedefaults.py#L204-L208
If
InstructionScheduleMap.add
is called by users, this will implicitly adds metadata of client (since we assume such schedule doesn't have metadata). This enables the pass to distinguish user-defined calibration from the backend provided calibrations. Thanks to this logic, we can selectively add user defined calibrations to the circuit.TODO