Executar jobs em um batch
Versões dos pacotes
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.3.0
qiskit-ibm-runtime~=0.43.1
Use o modo batch para enviar múltiplos jobs primitivos simultaneamente. A seguir estão exemplos de como trabalhar com batches.
Configurar para usar batches
Antes de iniciar um batch, você deve configurar o Qiskit Runtime e inicializá-lo como um serviço:
# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit qiskit-ibm-runtime
from qiskit_ibm_runtime import (
QiskitRuntimeService,
Batch,
SamplerV2 as Sampler,
EstimatorV2 as 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 um 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)
# 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,
SamplerV2 as Sampler,
EstimatorV2 as Estimator,
)
backend = service.least_busy(operational=True, simulator=False)
with Batch(backend=backend):
estimator = Estimator()
sampler = Sampler()
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)
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=133>), shape=(3, 2)), metadata={'circuit_metadata': {}})], metadata={'execution': {'execution_spans': ExecutionSpans([DoubleSliceSpan(<start='2026-01-15 07:47:58', stop='2026-01-15 07:48:05', size=24576>)])}, 'version': 2})
Determinar detalhes do batch
Para uma visão abrangente da configuração e do status de um batch, incluindo seu TTL interativo e máximo, use o método batch.details().
from qiskit_ibm_runtime import (
QiskitRuntimeService,
batch,
SamplerV2 as Sampler,
)
service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False)
with Batch(backend=backend) as batch:
print(batch.details())
{'id': 'ce8cf08d-b18e-4d56-ab51-eaff0b8190f4', 'backend_name': 'ibm_torino', '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_ibm_runtime import SamplerV2 as Sampler, Batch
from qiskit.circuit.random import random_circuit
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 um primitivo, o programa será executado no modo job, 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 o primitivo 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.