Ejecutar trabajos en una sesión
Versiones de paquetes
El código de esta página fue desarrollado con los siguientes requisitos. Recomendamos usar estas versiones o más recientes.
qiskit[all]~=2.3.0
qiskit-ibm-runtime~=0.43.1
scipy~=1.16.3
Los usuarios del Plan Abierto no pueden enviar trabajos en sesión. Los workloads deben ejecutarse en modo de trabajo o modo por lotes.
Usa sesiones cuando necesites acceso dedicado y exclusivo al QPU.
Configuración para usar sesiones
Antes de iniciar una sesión, debes configurar Qiskit Runtime e inicializarlo como servicio:
# 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()
Abrir una sesión
Puedes abrir una sesión de runtime usando el gestor de contexto with Session(...) o inicializando la clase Session.
Al iniciar una sesión, debes especificar un QPU pasando un objeto backend. La sesión comienza cuando su primer trabajo empieza a ejecutarse.
Si abres una sesión pero no envías ningún trabajo durante 30 minutos, la sesión se cierra automáticamente.
Clase Session
El siguiente bloque de código devolverá un error para los usuarios del Plan Abierto porque usa sesiones. Los workloads del Plan Abierto solo pueden ejecutarse en modo de trabajo o modo por lotes.
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()
Gestor de contexto
El gestor de contexto abre y cierra la sesión automáticamente.
El siguiente bloque de código devolverá un error para los usuarios del Plan Abierto porque usa sesiones. Los workloads del Plan Abierto solo pueden ejecutarse en modo de trabajo o modo por lotes.
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()
Duración de la sesión
El tiempo de vida máximo (TTL) de la sesión determina cuánto tiempo puede ejecutarse una sesión. Puedes establecer este valor con el parámetro max_time. Este valor debe superar el tiempo de ejecución del trabajo más largo.
Este temporizador comienza cuando la sesión se inicia. Al alcanzar el valor, la sesión se cierra. Los trabajos que estén en ejecución terminarán, pero los trabajos aún en cola fallarán.
El siguiente bloque de código devolverá un error para los usuarios del Plan Abierto porque usa sesiones. Los workloads del Plan Abierto solo pueden ejecutarse en modo de trabajo o modo por lotes.
with Session(backend=backend, max_time="25m"):
...
También existe un valor de tiempo de vida interactivo (TTL interactivo) que no se puede configurar. Si no se encolan trabajos de sesión dentro de esa ventana, la sesión se desactiva temporalmente.
Valores predeterminados:
| Tipo de instancia (Plan Abierto o Premium) | TTL interactivo | TTL máximo |
|---|---|---|
| Plan Premium | 60 seg* | 8 h* |
| * Ciertas instancias del Plan Premium pueden estar configuradas con un valor diferente. |
Para determinar el TTL máximo o el TTL interactivo de una sesión, sigue las instrucciones en Determinar detalles de la sesión y busca los valores max_time o interactive_timeout, respectivamente.
Finalizar una sesión
Una sesión termina en las siguientes circunstancias:
- Se alcanza el valor máximo de tiempo de espera (TTL), lo que provoca la cancelación de todos los trabajos en cola.
- La sesión se cancela manualmente, lo que provoca la cancelación de todos los trabajos en cola.
- La sesión se cierra manualmente. La sesión deja de aceptar nuevos trabajos, pero continúa ejecutando los trabajos en cola con prioridad.
- Si usas Session como gestor de contexto, es decir,
with Session(), la sesión se cierra automáticamente cuando el contexto termina (el mismo comportamiento que usarsession.close()).
Cerrar una sesión
Una sesión se cierra automáticamente cuando sale del gestor de contexto. Cuando se sale del gestor de contexto de la sesión, la sesión pasa al estado "En progreso, no acepta nuevos trabajos". Esto significa que la sesión termina de procesar todos los trabajos en ejecución o en cola hasta que se alcanza el valor máximo de tiempo de espera. Una vez completados todos los trabajos, la sesión se cierra inmediatamente. Esto permite al planificador ejecutar el siguiente trabajo sin esperar el tiempo de espera interactivo de la sesión, lo que reduce el tiempo promedio de espera en cola. No puedes enviar trabajos a una sesión cerrada.
El siguiente bloque de código devolverá un error para los usuarios del Plan Abierto porque usa sesiones. Los workloads del Plan Abierto solo pueden ejecutarse en modo de trabajo o modo por lotes.
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()
Si no estás usando un gestor de contexto, cierra la sesión manualmente para evitar costos no deseados. Puedes cerrar una sesión en cuanto termines de enviar trabajos. Cuando una sesión se cierra con session.close(), ya no acepta nuevos trabajos, pero los trabajos ya enviados seguirán ejecutándose hasta completarse y sus resultados podrán recuperarse.
El siguiente bloque de código devolverá un error para los usuarios del Plan Abierto porque usa sesiones. Los workloads del Plan Abierto solo pueden ejecutarse en modo de trabajo o modo por lotes.
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})
Verificar el estado de la sesión
Puedes consultar el estado de una sesión para entender su estado actual usando session.status() o visitando la página de Workloads.
El estado de la sesión puede ser uno de los siguientes:
Pending(Pendiente): La sesión no ha comenzado o ha sido desactivada. El siguiente trabajo de la sesión debe esperar en la cola como cualquier otro trabajo.In progress, accepting new jobs(En progreso, aceptando nuevos trabajos): La sesión está activa y acepta nuevos trabajos.In progress, not accepting new jobs(En progreso, no acepta nuevos trabajos): La sesión está activa pero no acepta nuevos trabajos. El envío de trabajos a la sesión es rechazado, pero los trabajos pendientes se ejecutarán hasta completarse. La sesión se cierra automáticamente una vez que todos los trabajos terminen.Closed(Cerrada): Se alcanzó el valor máximo de tiempo de espera de la sesión o la sesión fue cerrada explícitamente.
Determinar los detalles de la sesión
Para obtener una visión completa de la configuración y el estado de una sesión, usa el método session.details().
El siguiente bloque de código devolverá un error para los usuarios del Plan Abierto porque usa sesiones. Los workloads del Plan Abierto solo pueden ejecutarse en modo de trabajo o modo por lotes.
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}
Patrones de uso
Las sesiones son especialmente útiles para algoritmos que requieren comunicación frecuente entre recursos clásicos y cuánticos.
Ejemplo: ejecuta un workload iterativo que usa el optimizador clásico SciPy para minimizar una función de costo. En este modelo, SciPy usa la salida de la función de costo para calcular su siguiente entrada.
El siguiente bloque de código devolverá un error para los usuarios del Plan Abierto porque usa sesiones. Los workloads del Plan Abierto solo pueden ejecutarse en modo de trabajo o modo por lotes.
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()
Ejecutar dos algoritmos VQE en una sesión usando threading
Puedes aprovechar mejor una sesión ejecutando múltiples workloads simultáneamente. El siguiente ejemplo muestra cómo ejecutar dos algoritmos VQE, cada uno con un optimizador clásico diferente, de forma simultánea dentro de una única sesión. También se usan etiquetas de trabajo para diferenciar los trabajos de cada workload.
El siguiente bloque de código devolverá un error para los usuarios del Plan Abierto porque usa sesiones. Los workloads del Plan Abierto solo pueden ejecutarse en modo de trabajo o modo por lotes.
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()
Próximos pasos
- Prueba un ejemplo en el tutorial Algoritmo de optimización aproximada cuántica (QAOA).
- Consulta la referencia de la API de Session.
- Comprende los límites de trabajos al enviar un trabajo a un QPU de IBM®.
- Revisa las preguntas frecuentes sobre modos de ejecución.