Skip to main content
IBM Quantum Platform

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
    
Tip

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.

Caution

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.

./source_files/status_example.py
# 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.

./source_files/transpile_remote.py
# 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_circuit

En 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:

./source_files/transpile_remote.py (appended)
# 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")
./source_files/transpile_remote.py (appended)
# 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()
./source_files/transpile_remote.py (appended)
# 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.

./source_files/transpile_remote.py (appended)
# 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 None

Gestiona 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 tar y h5
  • 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.

./source_files/extract_tarfile.py
# 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

Recomendaciones
¿Le ha resultado útil esta página?
Informe de un error, de una errata o solicite contenido en GitHub.