Przejdź do głównej treści

Uruchamianie zadań w trybie wsadowym

Wersje pakietów

Kod na tej stronie został opracowany przy użyciu poniższych zależności. Zalecamy korzystanie z tych wersji lub nowszych.

qiskit[all]~=2.3.0
qiskit-ibm-runtime~=0.43.1

Użyj trybu wsadowego, aby jednocześnie przesyłać wiele zadań prymitywnych. Poniżej znajdziesz przykłady pracy z wsadami.

Konfiguracja do używania wsadów

Przed rozpoczęciem wsadu musisz skonfigurować Qiskit Runtime i zainicjować go jako usługę:

# 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()

Otwieranie wsadu

Możesz otworzyć wsad środowiska uruchomieniowego, używając menedżera kontekstu with Batch(...) lub inicjalizując klasę Batch. Podczas uruchamiania wsadu musisz określić QPU, przekazując obiekt backend. Wsad uruchamia się, gdy zaczyna wykonywać się jego pierwsze zadanie.

Klasa 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()

Menedżer kontekstu

Menedżer kontekstu automatycznie otwiera i zamyka wsad.

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()

Długość wsadu

Możesz zdefiniować maksymalny czas życia (TTL) wsadu za pomocą parametru max_time. Powinien on przekraczać czas wykonania najdłuższego zadania. Ten timer uruchamia się po starcie wsadu. Gdy wartość zostanie osiągnięta, wsad jest zamykany. Zadania, które są w trakcie wykonania, zostaną ukończone, ale zadania nadal w kolejce zakończą się niepowodzeniem.

with Batch(backend=backend, max_time="25m"):
...

Istnieje również interaktywny czas życia (interactive TTL), którego nie można konfigurować (1 minuta dla wszystkich planów). Jeśli w tym oknie nie zostaną kolejkowane żadne zadania wsadowe, wsad zostanie tymczasowo dezaktywowany.

Domyślne maksymalne wartości TTL:

Typ instancjiDomyślne maksymalne TTL
Wszystkie płatne plany8 godzin
Open10 minut

Aby określić maksymalne TTL lub interaktywne TTL wsadu, postępuj zgodnie z instrukcjami w Ustalanie szczegółów wsadu i szukaj wartości max_time lub interactive_timeout.

Zamykanie wsadu

Wsad automatycznie zamyka się po wyjściu z menedżera kontekstu. Gdy menedżer kontekstu wsadu zostanie opuszczony, wsad przechodzi w stan „W toku, nie przyjmuje nowych zadań". Oznacza to, że wsad kończy przetwarzanie wszystkich uruchomionych lub kolejkowanych zadań do momentu osiągnięcia maksymalnej wartości TTL. Po ukończeniu wszystkich zadań wsad jest natychmiast zamykany. Nie można przesyłać zadań do zamkniętego wsadu.

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()
wskazówka

Jeśli nie używasz menedżera kontekstu, ręcznie zamknij wsad. Jeśli pozostawisz wsad otwarty i później prześlesz do niego więcej zadań, możliwe jest, że maksymalne TTL zostanie osiągnięte przed rozpoczęciem kolejnych zadań, co spowoduje ich anulowanie. Możesz zamknąć wsad, gdy tylko skończysz przesyłać do niego zadania. Gdy wsad zostanie zamknięty za pomocą batch.close(), nie przyjmuje już nowych zadań, ale już przesłane zadania będą nadal wykonywane do ukończenia, a ich wyniki będą można pobrać.

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})

Ustalanie szczegółów wsadu

Aby uzyskać kompleksowy przegląd konfiguracji i stanu wsadu, w tym jego interaktywnego i maksymalnego TTL, użyj metody 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}

Rekonfiguracja zadań do przetwarzania równoległego

Istnieje wiele sposobów rekonfiguracji zadań, aby wykorzystać przetwarzanie równoległe zapewniane przez wsadowanie. Poniższy przykład pokazuje, jak podzielić długą listę obwodów na wiele zadań i uruchomić je jako wsad, aby skorzystać z przetwarzania równoległego.

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)
ostrożnie

Jeśli ustawisz backend=backend w prymitywie, program jest uruchamiany w trybie zadania, nawet jeśli jest wewnątrz kontekstu wsadu lub Session. Ustawianie backend=backend jest przestarzałe od wersji Qiskit Runtime v0.24.0. Zamiast tego użyj parametru mode.

Kolejne kroki

Zalecenia