Eseguire job in batch
Versioni dei pacchetti
Il codice in questa pagina è stato sviluppato utilizzando i seguenti requisiti. Consigliamo di usare queste versioni o successive.
qiskit[all]~=2.5.2
qiskit-ibm-runtime~=0.47.0
Usa batch mode per inviare più job di primitive contemporaneamente. Di seguito sono riportati esempi di lavoro con i batch.
Configurazione per l'uso dei batch
Prima di avviare un batch, devi configurare il client IBM Quantum Compute e inizializzarlo come servizio:
# Added by doQumentation — installs the packages this notebook needs if they are missing
import importlib.util
_needed = {"numpy": "numpy", "qiskit": "qiskit", "qiskit_ibm_runtime": "qiskit-ibm-runtime"}
_missing = [pip for module, pip in _needed.items()
if importlib.util.find_spec(module) is None]
# One at a time, so a package that fails to install does not block the others
for _pip in _missing:
%pip install -q {_pip}
if not _missing:
print("\u2713 All required packages are installed")
from qiskit_ibm_runtime import QiskitRuntimeService, Batch, Executor
# Legacy server-side primitive before qiskit-ibm-runtime 0.50.0
# from qiskit_ibm_runtime import Sampler, Estimator
# Client-side primitive introduced in qiskit-ibm-runtime 0.50.0
from qiskit_ibm_runtime.executor_sampler import Sampler
from qiskit_ibm_runtime.executor_estimator import Estimator
service = QiskitRuntimeService()
Aprire un batch
Puoi aprire un batch di runtime usando il context manager with Batch(...) oppure inizializzando direttamente la classe Batch.
Quando avvii un batch, devi specificare una QPU passando un oggetto backend. Il batch ha inizio quando viene eseguito il primo job.
Classe Batch
backend = service.least_busy(operational=True, simulator=False)
batch = Batch(backend=backend)
estimator = Estimator(mode=batch)
sampler = Sampler(mode=batch)
executor = Executor(mode=batch)
# Close the batch because no context manager was used.
batch.close()
Context manager
Il context manager apre e chiude il batch automaticamente.
from qiskit_ibm_runtime import Batch, Executor
# Legacy server-side primitive before qiskit-ibm-runtime 0.50.0
# from qiskit_ibm_runtime import Sampler, Estimator
# Client-side primitive introduced in qiskit-ibm-runtime 0.50.0
from qiskit_ibm_runtime.executor_sampler import Sampler
from qiskit_ibm_runtime.executor_estimator import Estimator
backend = service.least_busy(operational=True, simulator=False)
with Batch(backend=backend):
estimator = Estimator()
sampler = Sampler()
executor = Executor()
Durata del batch
Puoi definire il tempo di vita massimo (TTL) del batch tramite il parametro max_time. Questo valore dovrebbe superare il tempo di esecuzione del job più lungo. Il timer parte quando il batch viene avviato. Al raggiungimento del valore impostato, il batch viene chiuso. I job in esecuzione verranno completati, ma quelli ancora in coda verranno marcati come falliti.
with Batch(backend=backend, max_time="25m"):
...
Esiste anche un valore di tempo di vita interattivo (interactive TTL) che non è configurabile (1 minuto per tutti i piani). Se nessun job del batch viene messo in coda entro questa finestra temporale, il batch viene temporaneamente disattivato.
Valori TTL massimi predefiniti:
| Tipo di istanza | TTL massimo predefinito |
|---|---|
| Tutti i piani a pagamento | 8 ore |
| Open | 10 minuti |
Per determinare il TTL massimo o il TTL interattivo di un batch, segui le istruzioni in Determinare i dettagli del batch e cerca i valori max_time o interactive_timeout, rispettivamente.
Chiudere un batch
Un batch si chiude automaticamente quando si esce dal context manager. Quando il context manager del batch viene abbandonato, il batch passa allo stato "In corso, non accetta nuovi job". Questo significa che il batch termina l'elaborazione di tutti i job in esecuzione o in coda fino al raggiungimento del valore TTL massimo. Una volta completati tutti i job, il batch viene chiuso immediatamente. Non è possibile inviare job a un batch chiuso.
from qiskit.quantum_info import SparsePauliOp
from qiskit.circuit import QuantumCircuit, Parameter
from qiskit.transpiler import generate_preset_pass_manager
import numpy as np
# This cell is hidden from users
service = QiskitRuntimeService()
backend = service.least_busy()
# Define two circuits, each with one parameter with two parameters.
circuit = QuantumCircuit(2)
circuit.h(0)
circuit.cx(0, 1)
circuit.ry(Parameter("a"), 0)
circuit.cx(0, 1)
circuit.h(0)
circuit.measure_all()
pm = generate_preset_pass_manager(optimization_level=1, backend=backend)
transpiled_circuit = pm.run(circuit)
transpiled_circuit_sampler = transpiled_circuit
transpiled_circuit_sampler.measure_all()
params = np.random.uniform(size=(2, 3)).T
observables = [
[
SparsePauliOp(["XX", "IY"], [0.5, 0.5]).apply_layout(
transpiled_circuit.layout
)
],
[SparsePauliOp("XX").apply_layout(transpiled_circuit.layout)],
[SparsePauliOp("IY").apply_layout(transpiled_circuit.layout)],
]
sampler_pub = (transpiled_circuit_sampler, params)
estimator_pub = (transpiled_circuit_sampler, observables, params)
Il seguente codice richiede che tu fornisca le tue informazioni, come i PUB di Estimator e Sampler, e un Backend.
with Batch(backend=backend) as batch:
estimator = Estimator()
sampler = Sampler()
job1 = estimator.run([estimator_pub])
job2 = sampler.run([sampler_pub])
# The batch is no longer accepting jobs but the submitted job will run to completion.
result = job1.result()
result2 = job2.result()
Se non stai usando un context manager, chiudi il batch manualmente. Se lasci il batch aperto e invii altri job in seguito, è possibile che il TTL massimo venga raggiunto prima che i job successivi inizino l'esecuzione, causandone la cancellazione. Puoi chiudere un batch non appena hai terminato di inviare job. Quando un batch viene chiuso con batch.close(), non accetta più nuovi job, ma quelli già inviati verranno comunque eseguiti fino al completamento e i loro risultati potranno essere recuperati.
batch = Batch(backend=backend)
# If using qiskit-ibm-runtime earlier than 0.24.0, change `mode=` to `batch=`
estimator = Estimator(mode=batch)
sampler = Sampler(mode=batch)
job1 = estimator.run([estimator_pub])
job2 = sampler.run([sampler_pub])
print(f"Result1: {job1.result()}")
print(f"Result2: {job2.result()}")
# Manually close the batch. Running and queued jobs will run to completion.
batch.close()
Result1: PrimitiveResult([PubResult(data=DataBin(evs=np.ndarray(<shape=(3, 2), dtype=float64>), stds=np.ndarray(<shape=(3, 2), dtype=float64>), ensemble_standard_error=np.ndarray(<shape=(3, 2), dtype=float64>), shape=(3, 2)), metadata={'shots': 4096, 'target_precision': 0.015625, 'circuit_metadata': {}, 'resilience': {}, 'num_randomizations': 32})], metadata={'dynamical_decoupling': {'enable': False, 'sequence_type': 'XX', 'extra_slack_distribution': 'middle', 'scheduling_method': 'alap'}, 'twirling': {'enable_gates': False, 'enable_measure': True, 'num_randomizations': 'auto', 'shots_per_randomization': 'auto', 'interleave_randomizations': True, 'strategy': 'active-accum'}, 'resilience': {'measure_mitigation': True, 'zne_mitigation': False, 'pec_mitigation': False}, 'version': 2})
Result2: PrimitiveResult([SamplerPubResult(data=DataBin(meas=BitArray(<shape=(3, 2), num_shots=4096, num_bits=2>), meas0=BitArray(<shape=(3, 2), num_shots=4096, num_bits=156>), shape=(3, 2)), metadata={'circuit_metadata': {}})], metadata={'execution': {'execution_spans': ExecutionSpans([DoubleSliceSpan(<start='2026-09-01 07:46:49', stop='2026-09-01 07:46:56', size=24576>)])}, 'version': 2})
Determinare i dettagli del batch
Per una panoramica completa della configurazione e dello stato di un batch, incluso il suo TTL interattivo e massimo, usa il batch.details() method.
from qiskit_ibm_runtime import QiskitRuntimeService, Batch
service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False)
with Batch(backend=backend) as batch:
print(batch.details())
{'id': '947aa097-9055-42d4-9e58-ad1c2cdd9d5a', 'backend_name': 'ibm_marrakesh', 'interactive_timeout': 1, 'max_time': 28800, 'active_timeout': 28800, 'state': 'open', 'accepting_jobs': True, 'last_job_started': None, 'last_job_completed': None, 'started_at': None, 'closed_at': None, 'activated_at': None, 'mode': 'batch', 'usage_time': None}
Riconfigurare i job per l'elaborazione parallela
Esistono diversi modi per riconfigurare i tuoi job e sfruttare l'elaborazione parallela offerta dal batching. L'esempio seguente mostra come puoi suddividere un lungo elenco di circuiti in più job ed eseguirli come batch per sfruttare l'elaborazione parallela.
from qiskit.circuit.random import random_circuit
from qiskit_ibm_runtime import Batch
# Legacy server-side primitive before qiskit-ibm-runtime 0.50.0
# from qiskit_ibm_runtime import Sampler
# Client-side primitive introduced in qiskit-ibm-runtime 0.50.0
from qiskit_ibm_runtime.executor_sampler import Sampler
max_circuits = 100
circuits = [pm.run(random_circuit(5, 5)) for _ in range(5 * max_circuits)]
for circuit in circuits:
circuit.measure_active()
all_partitioned_circuits = []
for i in range(0, len(circuits), max_circuits):
all_partitioned_circuits.append(circuits[i : i + max_circuits])
jobs = []
start_idx = 0
with Batch(backend=backend):
sampler = Sampler()
for partitioned_circuits in all_partitioned_circuits:
job = sampler.run(partitioned_circuits)
jobs.append(job)
Se imposti backend=backend in una primitiva, il programma viene eseguito in job mode, anche all'interno di un contesto batch o sessione. L'impostazione di backend=backend è deprecata a partire da Qiskit Runtime v0.24.0. Usa invece il parametro mode.
Passi successivi
- Prova un esempio nel tutorial Combinare le opzioni di mitigazione degli errori con la primitiva Estimator.
- Consulta il riferimento alle API Batch.
- Scopri i limiti dei job quando invii un job a una QPU IBM.
- Consulta le FAQ sulle modalità di esecuzione.