Executar jobs em um batch
Package versions
O código desta página foi desenvolvido usando os seguintes requisitos. Recomendamos usar estas versões ou versões mais recentes.
qiskit[all]~=2.5.2
qiskit-ibm-runtime~=0.47.0
Use o batch mode para enviar vários jobs de primitivas simultaneamente. A seguir estão exemplos de como trabalhar com batches.
Configurar para usar batches
Antes de iniciar um batch, você deve configurar o cliente do IBM Quantum Compute e inicializá-lo como um serviço:
# 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()
Abrir um batch
Você pode abrir um batch de runtime usando o gerenciador de contexto with Batch(...) ou inicializando a classe Batch.
Ao iniciar um batch, você deve especificar uma QPU passando um objeto backend. O batch começa quando seu primeiro job inicia a execução.
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()
Gerenciador de contexto
O gerenciador de contexto abre e fecha o 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()
Duração do batch
Você pode definir o tempo máximo de vida (TTL) do batch com o parâmetro max_time. Esse valor deve superar o tempo de execução do job mais longo. O temporizador começa quando o batch é iniciado. Quando o valor é atingido, o batch é encerrado. Quaisquer jobs em execução serão finalizados, mas os jobs ainda na fila serão marcados como falhos.
with Batch(backend=backend, max_time="25m"):
...
Há também um valor de tempo de vida interativo (TTL interativo) que não pode ser configurado (1 minuto para todos os planos). Se nenhum job do batch for enfileirado dentro dessa janela, o batch é temporariamente desativado.
Valores padrão de TTL máximo:
| Tipo de instância | TTL Máximo Padrão |
|---|---|
| Todos os planos pagos | 8 horas |
| Open | 10 minutos |
Para determinar o TTL máximo ou o TTL interativo de um batch, siga as instruções em Determinar detalhes do batch e procure pelo valor max_time ou interactive_timeout, respectivamente.
Fechar um batch
Um batch é fechado automaticamente quando sai do gerenciador de contexto. Quando o gerenciador de contexto do batch é encerrado, o batch entra no status "Em andamento, não aceitando novos jobs". Isso significa que o batch continua processando todos os jobs em execução ou na fila até que o valor máximo de TTL seja atingido. Após a conclusão de todos os jobs, o batch é imediatamente fechado. Não é possível enviar jobs para um batch fechado.
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)
O código a seguir requer que você forneça suas próprias informações, como PUBs do Estimator e do Sampler, e um 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 você não estiver usando um gerenciador de contexto, feche o batch manualmente. Se você deixar o batch aberto e enviar mais jobs para ele posteriormente, é possível que o TTL máximo seja atingido antes que os jobs subsequentes comecem a ser executados, fazendo com que sejam cancelados. Você pode fechar um batch assim que terminar de enviar jobs para ele. Quando um batch é fechado com batch.close(), ele não aceita mais novos jobs, mas os jobs já enviados continuarão sendo executados até a conclusão e seus resultados poderão ser recuperados.
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})
Determinar detalhes do batch
Para uma visão geral abrangente da configuração e do status de um batch, incluindo seu TTL interativo e máximo, use o método 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}
Reconfigurar jobs para processamento paralelo
Há diversas maneiras de reconfigurar seus jobs para aproveitar o processamento paralelo proporcionado pelo batching. O exemplo a seguir mostra como você pode particionar uma longa lista de Circuits em múltiplos jobs e executá-los como um batch para aproveitar o processamento paralelo.
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 você definir backend=backend em uma primitiva, o programa será executado em job mode, mesmo que esteja dentro de um contexto de batch ou session. Definir backend=backend está obsoleto a partir do Qiskit Runtime v0.24.0. Em vez disso, use o parâmetro mode.
Próximos passos
- Experimente um exemplo no tutorial Combinar opções de mitigação de erros com a primitiva Estimator.
- Consulte a referência da API Batch.
- Entenda os Limites de jobs ao enviar um job para um QPU IBM®.
- Revise as perguntas frequentes sobre modos de execução.