Administrar recursos informáticos y de datos de Qiskit Serverless
El código de esta página se ha desarrollado teniendo en cuenta los siguientes requisitos. Recomendamos utilizar estas versiones o versiones más recientes.
qiskit[all]~=2.0.0 qiskit-ibm-runtime~=0.37.0 qiskit-serverless~=0.22.0
Qiskit Serverless está siendo actualizado y sus características están cambiando rápidamente. Durante esta fase de desarrollo, encontrará las notas de la versión y la documentación más reciente en la página « Qiskit Serverless » (Notas de la versión y documentación) de GitHub.
Con Qiskit Serverless, puedes gestionar la computación y los datos a través de tu patrón Qiskit, incluyendo CPUs, QPUs y otros aceleradores de computación.
Establecer estados detallados
Las cargas de trabajo sin servidor tienen varias etapas a lo largo de un flujo de trabajo. Por defecto, los siguientes estados son visibles con job.status():
- **
QUEUED**la carga de trabajo está en cola para los recursos clásicos - **
INITIALIZING**la carga de trabajo - **
RUNNING**la carga de trabajo se ejecuta actualmente en recursos clásicos - **
DONE**la carga de trabajo se ha completado con éxito
También puede establecer estados personalizados que describan con más detalle la etapa específica del flujo de trabajo, como se indica a continuación.
Si estás ejecutando las celdas de código localmente en un cuaderno, verás el comando %%writefile mágico. Al ejecutar las celdas con este comando especial, estas se guardan en el disco en lugar de ejecutarse.
# If you include the preceding `%%writefile` command (visible only when you read this locally in a
# notebook), running this cell saves to disk rather than executing the code.
from qiskit_serverless import update_status, Job
# # If your function has a mapping stage, particularly application functions, you can set the status
# to "RUNNING: MAPPING" as follows:
update_status(Job.MAPPING)
# # While handling transpilation, error suppression, and so forth, you can set the status to
# "RUNNING: OPTIMIZING_FOR_HARDWARE":
update_status(Job.OPTIMIZING_HARDWARE)
# # After you submit jobs to Qiskit Runtime, the underlying quantum job will be queued. You can set
# status to "RUNNING: WAITING_FOR_QPU":
update_status(Job.WAITING_QPU)
# # When the Qiskit Runtime job starts running on the QPU, set the following status
# "RUNNING: EXECUTING_QPU":
update_status(Job.EXECUTING_QPU)
## Once QPU is completed and post-processing has begun, set the status "RUNNING: POST_PROCESSING":
update_status(Job.POST_PROCESSING)Tras completar con éxito esta carga de trabajo (con save_result()), este estado se actualizará a DONE automáticamente.
Flujos de trabajo paralelos
Para tareas clásicas que se pueden paralelizar, utiliza el @distribute_task decorador para definir los requisitos de computación necesarios para ejecutar una tarea. Empieza recordando el transpile_remote.py ejemplo del tema «Escribe tu primer programa en Qiskit Serverless » con el siguiente código.
El siguiente código requiere que ya haya guardado sus credenciales.
# If you include the preceding `%%writefile` command (visible only when you read this locally in a
# notebook), running this cell saves to disk rather than executing the code.
from qiskit.transpiler import generate_preset_pass_manager
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit_serverless import distribute_task
service = QiskitRuntimeService()
@distribute_task(target={"cpu": 1})
def transpile_remote(circuit, optimization_level, backend):
"""
Transpiles an abstract circuit (or list of circuits)
into an ISA circuit for a given backend.
"""
pass_manager = generate_preset_pass_manager(
optimization_level=optimization_level,
backend=service.backend(backend)
)
isa_circuit = pass_manager.run(circuit)
return isa_circuitEn este ejemplo, ha decorado la función transpile_remote() con @distribute_task(target={"cpu": 1}). Cuando se ejecuta, crea una tarea de trabajador paralela asíncrona con un único núcleo de CPU y devuelve una referencia para realizar un seguimiento del trabajador. Para obtener el resultado, pase la referencia a la función get() . Podemos utilizarlo para ejecutar múltiples tareas paralelas:
# If you include the preceding `%%writefile` command
# (visible only when you read this locally in a
# notebook), running this cell saves to disk rather than
# executing the code.
from time import time
from qiskit_serverless import get, get_arguments, save_result, update_status, Job
# Get arguments
arguments = get_arguments()
circuit = arguments.get("circuit")
optimization_level = arguments.get("optimization_level")
backend = arguments.get("backend")# If you include the preceding `%%writefile` command
# (visible only when you read this locally in a
# notebook), running this cell saves to disk rather than executing the code.
# Start distributed transpilation
update_status(Job.OPTIMIZING_HARDWARE)
start_time = time()
transpile_worker_references = [
transpile_remote(circuit, optimization_level, backend)
for circuit in arguments.get("circuit_list")
]
transpiled_circuits = get(transpile_worker_references)
end_time = time()# If you include the preceding `%%writefile` command
# (visible only when you read this locally in a
# notebook), running this cell saves to disk rather than executing the code.
# Save result, with metadata
result = {
"circuits": transpiled_circuits,
"metadata": {
"resource_usage": {
"RUNNING: OPTIMIZING_FOR_HARDWARE": {
"CPU_TIME": end_time - start_time,
"QPU_TIME": 0,
},
}
},
}
save_result(result)Explora diferentes configuraciones de tareas
Puedes asignar de forma flexible CPU, GPU y memoria a tus tareas a través de @distribute_task(). Para Qiskit Serverless en IBM Quantum® Platform, cada programa está equipado con 16 núcleos de CPU y 32 GB de RAM, que se pueden asignar dinámicamente según sea necesario.
Los núcleos de CPU pueden asignarse como núcleos de CPU completos, o incluso como asignaciones fraccionadas, como se muestra a continuación.
La memoria se asigna en número de bytes. Recordemos que hay 1024 bytes en un kilobyte, 1024 kilobytes en un megabyte y 1024 megabytes en un gigabyte. Para asignar 2 GB de memoria a tu trabajador, necesitas asignar "mem": 2 * 1024 * 1024 * 1024.
# If you include the preceding `%%writefile` command
# (visible only when you read this locally in a
# notebook), running this cell saves to disk rather than executing the code.
@distribute_task(target={
"cpu": 16,
"mem": 2 * 1024 * 1024 * 1024
})
def transpile_remote(circuit, optimization_level, backend):
return NoneGestiona los datos de todo tu programa
Qiskit Serverless le permite gestionar archivos en el directorio /data a través de todos sus programas. Esto incluye varias limitaciones:
- Actualmente sólo se admiten los archivos
taryh5 - Esto es sólo un almacenamiento plano
/data, y no puede tener/data/folder/subdirectorios
A continuación se muestra cómo cargar archivos. Asegúrate de haber iniciado sesión en Qiskit Serverless con tu cuenta de IBM Quantum (consulta las instrucciones en Subir a Qiskit Serverless ).
import tarfile
from qiskit_serverless import IBMServerlessClient
# Create a tar
filename = "transpile_demo.tar"
file = tarfile.open(filename, "w")
file.add("./source_files/transpile_remote.py")
file.close()
# Get a reference to a QiskitFunction
serverless = IBMServerlessClient()
transpile_remote_demo = next(
program
for program in serverless.list()
if program.title == "transpile_remote_serverless"
)
# Upload the tar to Serverless data directory
serverless.file_upload(file=filename, function=transpile_remote_demo)Output:
'{"message":"/usr/src/app/media/5e1f442128cdf60018496a04/transpile_demo.tar"}'
A continuación, puedes listar todos los archivos de tu directorio data . Todos los programas pueden acceder a estos datos.
serverless.files(function=transpile_remote_demo)Output:
['classifier_name.pkl.tar', 'output.json.tar', 'transpile_demo.tar']
Esto puede hacerse desde un programa utilizando file_download() para descargar el archivo al entorno del programa, y descomprimiendo el tar.
# If you include the preceding `%%writefile` command
# (visible only when you read this locally in a
# notebook), running this cell saves to disk rather than executing the code.
import tarfile
from qiskit_serverless import IBMServerlessClient
# For `token`, use the 44-character API_KEY you created
# and saved from the IBM Quantum Platform Home dashboard
serverless = IBMServerlessClient(token="<YOUR_API_KEY>")
files = serverless.files()
demo_file = files[0]
downloaded_tar = serverless.file_download(demo_file)
with tarfile.open(downloaded_tar, 'r') as tar:
tar.extractall()En este punto, su programa puede interactuar con los archivos, como lo haría con un experimento local. file_upload() file_download(), y file_delete() pueden ser llamados desde su experimento local, o desde su programa cargado, para una gestión de datos consistente y flexible.
Próximos pasos
- Consulte un ejemplo completo que adapta el código existente a Qiskit Serverless.
- Lea un artículo en el que los investigadores utilizaron Qiskit Serverless y la supercomputación centrada en la cuántica para explorar la química cuántica.