Eseguire job in una sessione
Versioni dei pacchetti
Il codice in questa pagina è stato sviluppato utilizzando i seguenti requisiti. Si consiglia di usare queste versioni o versioni più recenti.
qiskit[all]~=2.5.2
qiskit-ibm-runtime~=0.47.0
scipy~=1.17.1
Gli utenti del piano Open non possono inviare job in sessione. I workload devono essere eseguiti in job mode o in batch mode.
Usa le sessioni quando hai bisogno di un accesso dedicato ed esclusivo alla QPU.
Configurazione per usare le sessioni
Prima di avviare una sessione, devi configurare il client IBM Quantum Compute e inizializzarlo come servizio:
# 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", "scipy": "scipy"}
_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, Session, 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()
Aprire una sessione
Puoi aprire una sessione di runtime usando il context manager with Session(...) oppure inizializzando la classe Session.
Quando avvii una sessione, devi specificare una QPU passando un oggetto backend. La sessione inizia quando il suo primo job viene eseguito.
Se apri una sessione ma non invii alcun job per 30 minuti, la sessione si chiude automaticamente.
Classe Session
Il seguente blocco di codice restituirà un errore agli utenti del piano Open perché utilizza le sessioni. I workload sul piano Open possono essere eseguiti solo in job mode o in batch mode.
backend = service.least_busy(operational=True, simulator=False)
session = Session(backend=backend)
estimator = Estimator(mode=session)
sampler = Sampler(mode=session)
executor = Executor(mode=session)
# Close the session because no context manager was used.
session.close()
Context manager
Il context manager apre e chiude la sessione automaticamente.
Il seguente blocco di codice restituirà un errore agli utenti del piano Open perché utilizza le sessioni. I workload sul piano Open possono essere eseguiti solo in job mode o in batch mode.
from qiskit_ibm_runtime import Session, 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 Session(backend=backend):
estimator = Estimator()
sampler = Sampler()
executor = Executor()
Durata della sessione
Il tempo di vita massimo della sessione (TTL) determina per quanto tempo può essere eseguita una sessione. Puoi impostare questo valore con il parametro max_time. Dovrebbe superare il tempo di esecuzione del job più lungo.
Questo timer parte quando la sessione inizia. Quando il valore viene raggiunto, la sessione viene chiusa. I job in esecuzione termineranno, mentre quelli ancora in coda falliscono.
Il seguente blocco di codice restituirà un errore agli utenti del piano Open perché utilizza le sessioni. I workload sul piano Open possono essere eseguiti solo in job mode o in batch mode.
with Session(backend=backend, max_time="25m"):
...
Esiste anche un valore di tempo di vita interattivo (interactive TTL) che non è configurabile. Se nessun job della sessione viene messo in coda entro quella finestra temporale, la sessione viene temporaneamente disattivata.
Valori predefiniti:
| Tipo di istanza (piano Open o Premium) | TTL interattivo | TTL massimo |
|---|---|---|
| Piano Premium | 60 sec* | 8 h* |
* Alcune istanze del piano Premium potrebbero essere configurate con un valore diverso.
Per determinare il TTL massimo o il TTL interattivo di una sessione, segui le istruzioni in Determinare i dettagli della sessione e cerca i valori max_time o interactive_timeout, rispettivamente.
Terminare una sessione
Una sessione termina nelle seguenti circostanze:
-
Il valore massimo di timeout (TTL) viene raggiunto, con conseguente annullamento di tutti i job in coda.
-
La sessione viene annullata manualmente, con conseguente annullamento di tutti i job in coda.
-
La sessione viene chiusa manualmente. La sessione smette di accettare nuovi job ma continua a eseguire i job in coda con priorità.
-
Se usi Session come context manager, ovvero
with Session(), la sessione viene chiusa automaticamente quando il contesto termina (stesso comportamento disession.close()).
Chiudere una sessione
Una sessione si chiude automaticamente quando esce dal context manager. Quando il context manager della sessione viene abbandonato, la sessione passa allo stato "In corso, non accetta nuovi job". Ciò significa che la sessione termina l'elaborazione di tutti i job in esecuzione o in coda fino al raggiungimento del valore di timeout massimo. Dopo il completamento di tutti i job, la sessione viene chiusa immediatamente. Questo consente allo scheduler di eseguire il job successivo senza attendere il timeout interattivo della sessione, riducendo così il tempo medio di accodamento dei job. Non è possibile inviare job a una sessione chiusa.
Il seguente blocco di codice restituirà un errore agli utenti del piano Open perché utilizza le sessioni. I workload sul piano Open possono essere eseguiti solo in job mode o in batch mode.
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()
Se non stai usando un context manager, chiudi manualmente la sessione per evitare costi indesiderati. Puoi chiudere una sessione non appena hai finito di inviarle job. Quando una sessione viene chiusa con session.close(), non accetta più nuovi job, ma i job già inviati verranno comunque eseguiti fino al completamento e i loro risultati potranno essere recuperati.
Il seguente blocco di codice restituirà un errore agli utenti del piano Open perché utilizza le sessioni. I workload sul piano Open possono essere eseguiti solo in job mode o in batch mode.
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=156>), shape=(3, 2)), metadata={'circuit_metadata': {}})], metadata={'execution': {'execution_spans': ExecutionSpans([DoubleSliceSpan(<start='2026-09-01 08:34:17', stop='2026-09-01 08:34:24', size=24576>)])}, 'version': 2})
Verificare lo stato della sessione
Puoi interrogare lo stato di una sessione per capirne la situazione attuale usando session.status() oppure consultando la pagina Workloads.
Lo stato della sessione può essere uno dei seguenti:
-
Pending: La sessione non è ancora iniziata o è stata disattivata. Il prossimo job della sessione deve attendere in coda come gli altri job. -
In progress, accepting new jobs: La sessione è attiva e accetta nuovi job. -
In progress, not accepting new jobs: La sessione è attiva ma non accetta nuovi job. L'invio di job alla sessione viene rifiutato, ma i job della sessione già in sospeso verranno eseguiti fino al completamento. La sessione viene chiusa automaticamente una volta terminati tutti i job. -
Closed: Il valore di timeout massimo della sessione è stato raggiunto oppure la sessione è stata chiusa esplicitamente.
Determinare i dettagli della sessione
Per una panoramica completa della configurazione e dello stato di una sessione, usa il session.details() method.
Il seguente blocco di codice restituirà un errore agli utenti del piano Open perché utilizza le sessioni. I workload sul piano Open possono essere eseguiti solo in job mode o in batch mode.
from qiskit_ibm_runtime import QiskitRuntimeService, Session
# Legacy server-side primitive before qiskit-ibm-runtime 0.50.0
# from qiskit_ibm_runtime import Estimator
# Client-side primitive introduced in qiskit-ibm-runtime 0.50.0
from qiskit_ibm_runtime.executor_estimator import Estimator
service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False)
with Session(backend=backend) as session:
print(session.details())
{'id': 'ff7977a5-ae7b-4509-9c84-bd1d7ff9f619', 'backend_name': 'ibm_marrakesh', '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}
Pattern di utilizzo
Le sessioni sono particolarmente utili per gli algoritmi che richiedono frequenti scambi di dati tra risorse classiche e quantistiche.
Esempio: esegui un workload iterativo che usa l'ottimizzatore classico SciPy per minimizzare una funzione di costo. In questo modello, SciPy usa l'output della funzione di costo per calcolare il suo prossimo input.
Il seguente blocco di codice restituirà un errore agli utenti del piano Open perché utilizza le sessioni. I workload sul piano Open possono essere eseguiti solo in job mode o in batch mode.
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()
Eseguire due algoritmi VQE in una sessione usando il threading
Puoi sfruttare al meglio una sessione eseguendo più workload contemporaneamente. L'esempio seguente mostra come eseguire due algoritmi VQE, ciascuno con un ottimizzatore classico diverso, simultaneamente all'interno di un'unica sessione. Vengono usati anche tag di job per distinguere i job dei diversi workload.
Il seguente blocco di codice restituirà un errore agli utenti del piano Open perché utilizza le sessioni. I workload sul piano Open possono essere eseguiti solo in job mode o in batch mode.
from concurrent.futures import ThreadPoolExecutor
# Legacy server-side primitive before qiskit-ibm-runtime 0.50.0
# from qiskit_ibm_runtime import Estimator
# Client-side primitive introduced in qiskit-ibm-runtime 0.50.0
from qiskit_ibm_runtime.executor_estimator import 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()
Passi successivi
- Prova un esempio nel tutorial Quantum approximate optimization algorithm (QAOA).
- Consulta il riferimento all'API Session.
- Scopri i limiti dei job quando invii un job a una QPU IBM®.
- Consulta le FAQ sulle modalità di esecuzione.