Configure runtime compilation for Qiskit Runtime
Runtime compilation techniques transform your circuit to minimize errors. Runtime compilation adds some classical pre-processing overhead to your overall runtime. Therefore, it is important to achieve a balance between perfecting your results and ensuring that your job completes in a reasonable amount of time.
To ensure faster and more efficient results, as of 1 March 2024, circuits and observables need to be transformed to only use instructions supported by the system (referred to as instruction set architecture (ISA) circuits and observables) before being submitted to the Qiskit Runtime primitives. See the transpilation documentation for instructions to transform circuits. Due to this change, the primitives will no longer perform layout or routing operations. Consequently, transpilation options referring to those tasks will no longer have any effect. By default, all V1 primitives optimize the input circuits. To bypass all optimization when using a V1 primitive, set optimization_level=0
.
Exception: When you initialize the Qiskit Runtime Service with the Q-CTRL channel strategy (example below), abstract circuits are still supported.
service = QiskitRuntimeService(channel="ibm_cloud", channel_strategy="q-ctrl")
Set the optimization level (V1 primitives only)
The optimization_level
setting specifies how much optimization to perform on the circuits. Higher levels generate more optimized circuits, at the expense of longer compile times.
Optimization levels 2 and 3 behave identically to level 1.
Optimization Level | Estimator & Sampler |
---|---|
0 | No optimization: typically used for hardware characterization or debugging |
1, 2, 3 | Light optimization:
|
If using an IBM Cloud® Qiskit Runtime service instance with Q-CTRL performance management enabled, there is no need to specify runtime optimization or resilience levels, as the strategy includes an automatic preset.
Q-CTRL defaults to optimization_level=3
and resilience_level=1
.
Setting optimization_level
or resilience_level
equal to 0 will result in an
execution error. Levels 1, 2, and 3 are permitted but will not impact performance.
Setting other options will likewise not impact performance, and it may result in a
runtime warning. For more information visit the Q-CTRL documentation(opens in a new tab).
Example: configure Estimator with optimization levels
from qiskit_ibm_runtime import QiskitRuntimeService, EstimatorV2 as Estimator
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit.circuit.library import RealAmplitudes
from qiskit.quantum_info import SparsePauliOp
service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False)
psi = RealAmplitudes(num_qubits=2, reps=2)
H = SparsePauliOp.from_list([("II", 1), ("IZ", 2), ("XI", 3)])
theta = [0, 1, 1, 2, 3, 5]
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
psi = pm.run(psi)
H = H.apply_layout(psi.layout)
estimator = Estimator(mode=backend)
job = estimator.run([(psi, H, theta)])
psi1_H1 = job.result()[0]
from qiskit_ibm_runtime import QiskitRuntimeService, Estimator, Options
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit.circuit.library import RealAmplitudes
from qiskit.quantum_info import SparsePauliOp
service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False)
options = Options(optimization_level=1)
psi = RealAmplitudes(num_qubits=2, reps=2)
H = SparsePauliOp.from_list([("II", 1), ("IZ", 2), ("XI", 3)])
theta = [0, 1, 1, 2, 3, 5]
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
psi = pm.run(psi)
H = H.apply_layout(psi.layout)
estimator = Estimator(options=options, backend=backend)
job = estimator.run(circuits=[psi], observables=[H], parameter_values=[theta])
psi1_H1 = job.result()
If the optimization level is not specified, the service uses optimization_level = 1
.
Advanced runtime compilation options
In the V2 primitives, you can explicitly enable and disable individual error mitigation/suppression methods, such as dynamical decoupling.
Dynamical decoupling is not supported when the input circuits are dynamic.
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit_ibm_runtime import SamplerV2 as Sampler
service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False)
sampler = Sampler(backend)
# Turn on dynamical decoupling with sequence XpXm.
sampler.options.dynamical_decoupling.enable = True
sampler.options.dynamical_decoupling.sequence_type = "XpXm"
print(f">>> dynamical decoupling sequence to use: {sampler.options.dynamical_decoupling.sequence_type}")
Because all input must be ISA, options.transpilation.xxx will be ignored.
Next steps
- Try a tutorial that uses optimization levels, such as the Variational quantum eigensolver(opens in a new tab) tutorial.
- Learn how to transpile locally in the Transpile section.
- Try the Submit pre-transpiled circuits(opens in a new tab) tutorial.