Uruchamianie zadań w sesji
Wersje pakietów
Kod na tej stronie został opracowany przy użyciu następujących wymagań. Zalecamy korzystanie z tych wersji lub nowszych.
qiskit[all]~=2.3.0
qiskit-ibm-runtime~=0.43.1
scipy~=1.16.3
Użytkownicy planu Open Plan nie mogą przesyłać zadań sesji. Zadania muszą być uruchamiane w trybie zadań lub trybie wsadowym.
Używaj sesji, gdy potrzebujesz dedykowanego i wyłącznego dostępu do QPU.
Konfiguracja do korzystania z sesji
Przed uruchomieniem sesji 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 scipy
from qiskit_ibm_runtime import (
QiskitRuntimeService,
Session,
SamplerV2 as Sampler,
EstimatorV2 as Estimator,
)
service = QiskitRuntimeService()
Otwieranie sesji
Sesję runtime możesz otworzyć przy użyciu menedżera kontekstu with Session(...) lub przez zainicjowanie klasy Session.
Przy uruchamianiu sesji musisz podać QPU, przekazując obiekt backend. Sesja startuje, gdy zaczyna się wykonywanie jej pierwszego zadania.
Jeśli otworzysz sesję, ale nie prześlesz do niej żadnych zadań przez 30 minut, sesja automatycznie się zamknie.
Klasa Session
Poniższy blok kodu zwróci błąd dla użytkowników planu Open Plan, ponieważ korzysta z sesji. Zadania w planie Open Plan mogą być uruchamiane wyłącznie w trybie zadań lub trybie wsadowym.
backend = service.least_busy(operational=True, simulator=False)
session = Session(backend=backend)
estimator = Estimator(mode=session)
sampler = Sampler(mode=session)
# Close the session because no context manager was used.
session.close()
Menedżer kontekstu
Menedżer kontekstu automatycznie otwiera i zamyka sesję.
Poniższy blok kodu zwróci błąd dla użytkowników planu Open Plan, ponieważ korzysta z sesji. Zadania w planie Open Plan mogą być uruchamiane wyłącznie w trybie zadań lub trybie wsadowym.
from qiskit_ibm_runtime import (
Session,
SamplerV2 as Sampler,
EstimatorV2 as Estimator,
)
backend = service.least_busy(operational=True, simulator=False)
with Session(backend=backend):
estimator = Estimator()
sampler = Sampler()
Czas trwania sesji
Maksymalny czas życia sesji (TTL) określa, jak długo sesja może działać. Możesz ustawić tę wartość za pomocą parametru max_time. Powinna ona przekraczać czas wykonywania najdłuższego zadania.
Ten licznik czasu startuje w momencie uruchomienia sesji. Po osiągnięciu wartości sesja jest zamykana. Zadania w trakcie wykonywania zostaną dokończone, natomiast zadania wciąż oczekujące w kolejce zakończą się błędem.
Poniższy blok kodu zwróci błąd dla użytkowników planu Open Plan, ponieważ korzysta z sesji. Zadania w planie Open Plan mogą być uruchamiane wyłącznie w trybie zadań lub trybie wsadowym.
with Session(backend=backend, max_time="25m"):
...
Istnieje również wartość interaktywnego czasu życia (interactive TTL), której nie można konfigurować. Jeśli w tym oknie czasowym nie zostaną ustawione w kolejce żadne zadania sesji, sesja zostanie tymczasowo dezaktywowana.
Wartości domyślne:
| Typ instancji (plan Open lub Premium) | Interaktywny TTL | Maksymalny TTL |
|---|---|---|
| Plan Premium | 60 s* | 8 h* |
| * Niektóre instancje planu Premium mogą mieć skonfigurowane inne wartości. |
Aby określić maksymalny TTL sesji lub interaktywny TTL, postępuj zgodnie z instrukcjami w sekcji Sprawdzanie szczegółów sesji i wyszukaj odpowiednio wartość max_time lub interactive_timeout.
Kończenie sesji
Sesja kończy się w następujących okolicznościach:
- Osiągnięta zostaje maksymalna wartość limitu czasu (TTL), co powoduje anulowanie wszystkich zadań oczekujących w kolejce.
- Sesja jest ręcznie anulowana, co powoduje anulowanie wszystkich zadań oczekujących w kolejce.
- Sesja jest ręcznie zamykana. Sesja przestaje przyjmować nowe zadania, ale kontynuuje wykonywanie zadań z kolejki z priorytetem.
- Jeśli używasz Session jako menedżera kontekstu, tzn.
with Session(), sesja jest automatycznie zamykana po zakończeniu kontekstu (takie samo zachowanie jak przy użyciusession.close()).
Zamykanie sesji
Sesja zamyka się automatycznie po opuszczeniu menedżera kontekstu. Gdy menedżer kontekstu sesji jest opuszczany, sesja przechodzi w stan „W trakcie, nie przyjmuje nowych zadań". Oznacza to, że sesja kończy przetwarzanie wszystkich uruchomionych lub oczekujących w kolejce zadań do momentu osiągnięcia maksymalnej wartości limitu czasu. Po ukończeniu wszystkich zadań sesja jest natychmiast zamykana. Dzięki temu harmonogram może uruchomić kolejne zadanie bez czekania na interaktywny limit czasu sesji, co skraca średni czas oczekiwania zadań w kolejce. Nie możesz przesyłać zadań do zamkniętej sesji.
Poniższy blok kodu zwróci błąd dla użytkowników planu Open Plan, ponieważ korzysta z sesji. Zadania w planie Open Plan mogą być uruchamiane wyłącznie w trybie zadań lub trybie wsadowym.
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()
# Create parameters and mapped observables to submit
params = np.random.uniform(size=(2, 3)).T
observables = [
SparsePauliOp(["XX", "IY"], [0.5, 0.5]),
SparsePauliOp("XX"),
SparsePauliOp("IY"),
]
mapped_observables = [
[observable.apply_layout(transpiled_circuit.layout)]
for observable in observables
]
sampler_pub = (transpiled_circuit_sampler, params)
estimator_pub = (transpiled_circuit_sampler, mapped_observables, params)
with Session(backend=backend) as session:
estimator = Estimator()
sampler = Sampler()
job1 = estimator.run([estimator_pub])
job2 = sampler.run([sampler_pub])
# The session is no longer accepting jobs but the submitted job will run to completion.
result = job1.result()
result2 = job2.result()
Jeśli nie używasz menedżera kontekstu, ręcznie zamknij sesję, aby uniknąć niepożądanych kosztów. Możesz zamknąć sesję zaraz po zakończeniu przesyłania do niej zadań. Gdy sesja zostanie zamknięta przy użyciu session.close(), nie przyjmuje już nowych zadań, ale przesłane wcześniej zadania nadal będą wykonywane do zakończenia i ich wyniki będzie można pobrać.
Poniższy blok kodu zwróci błąd dla użytkowników planu Open Plan, ponieważ korzysta z sesji. Zadania w planie Open Plan mogą być uruchamiane wyłącznie w trybie zadań lub trybie wsadowym.
session = Session(backend=backend)
# If using qiskit-ibm-runtime earlier than 0.24.0, change `mode=` to `session=`
estimator = Estimator(mode=session)
sampler = Sampler(mode=session)
job1 = estimator.run([estimator_pub])
job2 = sampler.run([sampler_pub])
print(f"Result1: {job1.result()}")
print(f"Result2: {job2.result()}")
# Manually close the session. Running and queued jobs will run to completion.
session.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:53:15', stop='2026-01-15 07:53:21', size=24576>)])}, 'version': 2})
Sprawdzanie statusu sesji
Możesz zapytać o status sesji, aby poznać jej bieżący stan, używając session.status() lub przeglądając stronę Workloads.
Status sesji może przyjmować jedną z następujących wartości:
Pending: Sesja nie została uruchomiona lub została dezaktywowana. Następne zadanie sesji musi czekać w kolejce jak inne zadania.In progress, accepting new jobs: Sesja jest aktywna i przyjmuje nowe zadania.In progress, not accepting new jobs: Sesja jest aktywna, ale nie przyjmuje nowych zadań. Przesyłanie zadań do sesji jest odrzucane, ale oczekujące zadania sesji będą wykonane do końca. Sesja zostaje automatycznie zamknięta po zakończeniu wszystkich zadań.Closed: Osiągnięto maksymalną wartość limitu czasu sesji lub sesja została jawnie zamknięta.
Sprawdzanie szczegółów sesji
Aby uzyskać pełny przegląd konfiguracji i statusu sesji, użyj metody session.details().
Poniższy blok kodu zwróci błąd dla użytkowników planu Open Plan, ponieważ korzysta z sesji. Zadania w planie Open Plan mogą być uruchamiane wyłącznie w trybie zadań lub trybie wsadowym.
from qiskit_ibm_runtime import (
QiskitRuntimeService,
Session,
EstimatorV2 as Estimator,
)
service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False)
with Session(backend=backend) as session:
print(session.details())
{'id': 'be84569d-86b5-4a7f-be5e-7d33e80dc220', 'backend_name': 'ibm_torino', 'interactive_timeout': 60, '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': 'dedicated', 'usage_time': None}
Wzorce użycia
Sesje są szczególnie przydatne w algorytmach wymagających częstej komunikacji między zasobami klasycznymi i kwantowymi.
Przykład: uruchom iteracyjne obciążenie robocze, które używa klasycznego optymalizatora SciPy do minimalizacji funkcji kosztu. W tym modelu SciPy wykorzystuje wynik funkcji kosztu do obliczenia następnego wejścia.
Poniższy blok kodu zwróci błąd dla użytkowników planu Open Plan, ponieważ korzysta z sesji. Zadania w planie Open Plan mogą być uruchamiane wyłącznie w trybie zadań lub trybie wsadowym.
from scipy.optimize import minimize
from qiskit.circuit.library import efficient_su2
def cost_func(params, ansatz, hamiltonian, estimator):
# Return estimate of energy from estimator
energy = sum(
estimator.run([(ansatz, hamiltonian, params)]).result()[0].data.evs
)
return energy
hamiltonian = SparsePauliOp.from_list(
[("YZ", 0.3980), ("ZI", -0.3980), ("ZZ", -0.0113), ("XX", 0.1810)]
)
su2_ansatz = efficient_su2(hamiltonian.num_qubits)
pm = generate_preset_pass_manager(backend=backend, optimization_level=3)
ansatz = pm.run(su2_ansatz)
mapped_hamiltonian = [
operator.apply_layout(ansatz.layout) for operator in hamiltonian
]
num_params = ansatz.num_parameters
x0 = 2 * np.pi * np.random.random(num_params)
session = Session(backend=backend)
# If using qiskit-ibm-runtime earlier than 0.24.0, change `mode=` to `session=`
estimator = Estimator(mode=session, options={"default_shots": int(1e4)})
res = minimize(
cost_func,
x0,
args=(ansatz, mapped_hamiltonian, estimator),
method="cobyla",
options={"maxiter": 25},
)
# Close the session because no context manager was used.
session.close()
Uruchamianie dwóch algorytmów VQE w sesji przy użyciu wątków
Możesz efektywniej wykorzystać sesję, uruchamiając jednocześnie wiele obciążeń roboczych. Poniższy przykład pokazuje, jak można uruchomić dwa algorytmy VQE, każdy z innym klasycznym optymalizatorem, jednocześnie w ramach jednej sesji. Znaczniki zadań są również używane do rozróżniania zadań z poszczególnych obciążeń roboczych.
Poniższy blok kodu zwróci błąd dla użytkowników planu Open Plan, ponieważ korzysta z sesji. Zadania w planie Open Plan mogą być uruchamiane wyłącznie w trybie zadań lub trybie wsadowym.
from concurrent.futures import ThreadPoolExecutor
from qiskit_ibm_runtime import EstimatorV2 as Estimator
def minimize_thread(estimator, method):
return minimize(
cost_func,
x0,
args=(ansatz, mapped_hamiltonian, estimator),
method=method,
options={"maxiter": 25},
)
with Session(backend=backend), ThreadPoolExecutor() as executor:
estimator1 = Estimator()
estimator2 = Estimator()
# Use different tags to differentiate the jobs.
estimator1.options.environment.job_tags = ["cobyla"]
estimator2.options.environment.job_tags = ["nelder-mead"]
# Submit the two workloads.
cobyla_future = executor.submit(minimize_thread, estimator1, "cobyla")
nelder_mead_future = executor.submit(
minimize_thread, estimator2, "nelder-mead"
)
# Get workload results.
cobyla_result = cobyla_future.result()
nelder_mead_result = nelder_mead_future.result()
Następne kroki
- Wypróbuj przykład w samouczku Kwantowy algorytm przybliżonej optymalizacji (QAOA).
- Zapoznaj się z dokumentacją Session API.
- Dowiedz się więcej o limitach zadań podczas wysyłania zadania do QPU IBM®.
- Zapoznaj się z FAQ dotyczącymi trybów wykonania.