انتقل إلى المحتوى الرئيسي

تشغيل المهام في وضع الدُفعات

Package versions

The code on this page was developed using the following requirements. We recommend using these versions or newer.

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

استخدم وضع الدُفعات لإرسال عدة مهام primitive في آنٍ واحد. فيما يلي أمثلة على التعامل مع الدُفعات.

الإعداد لاستخدام الدُفعات

قبل بدء دُفعة، عليك إعداد Qiskit Runtime وتهيئته كخدمة:

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

فتح دُفعة

يمكنك فتح دُفعة runtime باستخدام مدير السياق with Batch(...) أو بإنشاء نسخة من كلاس Batch مباشرةً. عند بدء الدُفعة، يجب تحديد وحدة المعالجة الكمية (QPU) بتمرير كائن backend. تبدأ الدُفعة فعلياً عند تنفيذ أول مهمة فيها.

كلاس 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()

مدير السياق

يفتح مدير السياق الدُفعةَ ويُغلقها تلقائياً.

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

مدة الدُفعة

يمكنك تحديد الحد الأقصى لوقت حياة الدُفعة (TTL) باستخدام المعامل max_time. ينبغي أن تتجاوز هذه القيمة زمن تنفيذ أطول مهمة. يبدأ هذا العداد عند انطلاق الدُفعة، وحين تُبلغ القيمة المحددة تُغلَق الدُفعة تلقائياً؛ فالمهام التي تعمل ستكتمل، أما المهام المنتظرة في الطابور فستُلغى.

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

ثمة أيضاً قيمة وقت حياة تفاعلي (interactive TTL) غير قابلة للضبط (دقيقة واحدة لجميع الخطط). إذا لم تُضَف أي مهمة جديدة خلال هذه النافذة الزمنية، توقفت الدُفعة مؤقتاً.

القيم الافتراضية للحد الأقصى لـ TTL:

نوع الاشتراكالحد الأقصى الافتراضي لـ TTL
جميع الخطط المدفوعة8 ساعات
Open10 دقائق

لمعرفة الحد الأقصى لـ TTL أو قيمة TTL التفاعلي لدُفعة ما، اتبع التعليمات في معرفة تفاصيل الدُفعة وابحث عن قيمتَي max_time أو interactive_timeout على التوالي.

إغلاق دُفعة

تُغلَق الدُفعة تلقائياً عند الخروج من مدير السياق. حين ينتهي مدير السياق، تنتقل الدُفعة إلى حالة "قيد التنفيذ، لا تقبل مهام جديدة". هذا يعني أن الدُفعة تُكمل معالجة جميع المهام الجارية أو المنتظرة حتى تُبلَغ قيمة الحد الأقصى لـ TTL. وبمجرد اكتمال جميع المهام، تُغلَق الدُفعة فوراً. لا يمكنك إرسال مهام إلى دُفعة مغلقة.

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()
نصيحة

إن لم تكن تستخدم مدير السياق، أغلق الدُفعة يدوياً. إذا تركت الدُفعة مفتوحة وأرسلت إليها مهام لاحقاً، فقد تُبلَغ قيمة الحد الأقصى لـ TTL قبل أن تبدأ تلك المهام في التنفيذ، فتُلغى. يمكنك إغلاق الدُفعة فور الانتهاء من إرسال جميع مهامك إليها. حين تُغلق دُفعة باستخدام batch.close()، لن تقبل مهام جديدة، لكن المهام المُرسَلة مسبقاً ستُكمل تنفيذها ويمكن استرجاع نتائجها.

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

معرفة تفاصيل الدُفعة

للحصول على نظرة شاملة على إعدادات الدُفعة وحالتها، بما في ذلك TTL التفاعلي والحد الأقصى لـ TTL، استخدم الأسلوب 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}

إعادة ضبط المهام للمعالجة المتوازية

ثمة طرق متعددة لإعادة ضبط مهامك للاستفادة من المعالجة المتوازية التي توفرها الدُفعات. يوضح المثال التالي كيف يمكنك تقسيم قائمة طويلة من الدوائر إلى عدة مهام وتشغيلها كدُفعة للاستفادة من المعالجة المتوازية.

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)
تنبيه

إذا ضبطت backend=backend في primitive، فسيُشغَّل البرنامج في وضع المهمة الفردية (job mode) حتى لو كان داخل سياق دُفعة أو جلسة. استخدام backend=backend أصبح مُهمَلاً منذ Qiskit Runtime v0.24.0؛ استخدم معامل mode بدلاً منه.

الخطوات التالية

Recommendations