รันงานในโหมด Batch
Package versions
โค้ดในหน้านี้พัฒนาขึ้นโดยใช้ requirement ต่อไปนี้ แนะนำให้ใช้เวอร์ชันเหล่านี้หรือใหม่กว่า
qiskit[all]~=2.5.2
qiskit-ibm-runtime~=0.47.0
ใช้ batch mode เพื่อส่ง primitive job หลายรายการพร้อมกัน ต่อไปนี้เป็นตัวอย่างการทำงานกับ batch
ตั้งค่าเพื่อใช้งาน batch
ก่อนเริ่ม batch ต้องตั้งค่า IBM Quantum Compute client และ initialize เป็น service ก่อน:
# 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()
เปิด batch
เปิด runtime batch ได้โดยใช้ context manager with Batch(...) หรือสร้าง instance ของ class Batch
เมื่อเริ่ม batch ต้องระบุ QPU โดยส่ง object backend เข้าไป batch จะเริ่มทำงานเมื่อ job แรกเริ่ม execute
Batch class
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
Context manager จะเปิดและปิด batch โดยอัตโนมัติ
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()
ระยะเวลา Batch
กำหนดเวลาสูงสุดที่ batch จะมีชีวิต (TTL) ได้ด้วย parameter max_time ควรตั้งค่าให้มากกว่าเวลา execute ของ job ที่ยาวที่สุด timer นี้เริ่มนับเมื่อ batch เริ่มทำงาน เมื่อถึงค่าที่กำหนด batch จะปิดลง job ที่กำลังรันอยู่จะทำงานจนเสร็จ แต่ job ที่ยังรออยู่ใน queue จะถูก fail
with Batch(backend=backend, max_time="25m"):
...
นอกจากนี้ยังมีค่า interactive time to live (interactive TTL) ที่ไม่สามารถปรับแต่งได้ (1 นาทีสำหรับทุกแผน) ถ้าไม่มี batch job ถูก queue ภายในช่วงเวลานั้น batch จะถูกปิดการใช้งานชั่วคราว
ค่า maximum TTL เริ่มต้น:
| ประเภท Instance | Maximum TTL เริ่มต้น |
|---|---|
| แผนแบบเสียเงินทุกประเภท | 8 ชั่วโมง |
| Open | 10 นาที |
เพื่อดู maximum TTL หรือ interactive TTL ของ batch ให้ทำตามขั้นตอนใน ดูรายละเอียด batch และหาค่า max_time หรือ interactive_timeout ตามลำดับ
ปิด batch
Batch จะปิดโดยอัตโนมัติเมื่อออกจาก context manager เมื่อออกจาก batch context manager แล้ว batch จะเข้าสู่สถานะ "In progress, not accepting new jobs" หมายความว่า batch จะยังคงประมวลผล job ที่กำลังรันหรืออยู่ใน queue ทั้งหมดจนกว่าจะถึงค่า maximum TTL หลังจาก job ทั้งหมดเสร็จสิ้น batch จะปิดทันที ไม่สามารถส่ง job ไปยัง batch ที่ปิดแล้วได้
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)
โค้ดต่อไปนี้ต้องการให้คุณระบุข้อมูลของคุณเอง เช่น PUB ของ Estimator และ Sampler และ 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()
ถ้าไม่ได้ใช้ context manager ให้ปิด batch ด้วยตนเอง ถ้าปล่อย batch ค้างไว้และส่ง job เพิ่มเติมในภายหลัง อาจหมดเวลา maximum TTL ก่อนที่ job ที่ส่งตามมาจะเริ่มรัน ทำให้ job เหล่านั้นถูกยกเลิก ปิด batch ได้ทันทีที่ส่ง job ครบแล้ว เมื่อปิด batch ด้วย batch.close() batch จะไม่รับ job ใหม่ แต่ job ที่ส่งไปแล้วจะยังคงรันจนเสร็จและดึงผลลัพธ์ได้
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})
ดูรายละเอียด batch
ใช้ batch.details() method เพื่อดูภาพรวมการกำหนดค่าและสถานะทั้งหมดของ batch รวมถึง interactive TTL และ max TTL
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}
ปรับแต่ง job เพื่อประมวลผลแบบขนาน
มีหลายวิธีในการปรับแต่ง job เพื่อใช้ประโยชน์จากการประมวลผลแบบขนานที่ batch มอบให้ ตัวอย่างต่อไปนี้แสดงวิธีการแบ่ง Circuit รายการยาวออกเป็น job หลายรายการและรันเป็น batch เพื่อใช้ประโยชน์จากการประมวลผลแบบขนาน
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)
ถ้าตั้งค่า backend=backend ใน primitive โปรแกรมจะรันใน job mode แม้จะอยู่ภายใน batch หรือ session context ก็ตาม การตั้งค่า backend=backend เป็น deprecated ตั้งแต่ Qiskit Runtime v0.24.0 แนะนำให้ใช้ parameter mode แทน
ขั้นตอนถัดไป
- ลองทำตัวอย่างใน tutorial รวม error mitigation หลายตัวเลือกกับ Estimator primitive
- ดู reference ของ Batch API
- ทำความเข้าใจ ขีดจำกัดของ Job เมื่อส่ง job ไปยัง IBM® QPU
- ทบทวน คำถามที่พบบ่อยเกี่ยวกับ execution mode.