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.3.0
qiskit-ibm-runtime~=0.43.1
scipy~=1.16.3
Gli utenti del piano Open non possono inviare job in sessione. I workload devono essere eseguiti in modalità job o in modalità batch.
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 Qiskit Runtime e inizializzarlo come servizio:
# 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()
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 modalità job o in modalità batch.
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()
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 modalità job o in modalità batch.
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()
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, ma quelli ancora in coda vengono annullati con errore.
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 modalità job o in modalità batch.
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 modalità job o in modalità 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()
# 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 modalità job o in modalità batch.
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})
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 metodo session.details().
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 modalità job o in modalità batch.
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}
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 modalità job o in modalità batch.
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 modalità job o in modalità batch.
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()
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.