Skip to main content
IBM Quantum Platform

Gerencie recursos de computação e dados d Qiskit Serverless

  • O código desta página foi desenvolvido usando os seguintes requisitos. Recomendamos o uso dessas versões ou de versões mais recentes.

    qiskit[all]~=2.0.0
    qiskit-ibm-runtime~=0.37.0
    qiskit-serverless~=0.22.0
    
Tip

Qiskit Serverless está recebendo uma atualização e seus recursos estão mudando rapidamente. Durante esta fase de desenvolvimento, encontre notas de lançamento e a documentação mais recente na página Qiskit ServerlessGitHub.

Com o Qiskit Serverless, você pode gerenciar a computação e os dados em seu padrão Qiskit, incluindo CPUs, QPUs e outros aceleradores de computação.


Definir status detalhados

As cargas de trabalho sem servidor têm vários estágios em um fluxo de trabalho. Por padrão, os seguintes status podem ser visualizados em job.status():

  • QUEUED: a carga de trabalho está na fila de espera dos recursos clássicos
  • INITIALIZING: a carga de trabalho é configurada
  • **RUNNING**carga de trabalho: a carga de trabalho está sendo executada atualmente em recursos clássicos
  • DONE: a carga de trabalho foi concluída com êxito

Você também pode definir status personalizados que descrevem melhor o estágio específico do fluxo de trabalho, como segue.

Caution

Se você estiver executando as células de código localmente em um notebook, verá o comando %%writefile mágico. A execução de células com este comando especial as salva no disco, em vez de executá-las.

./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)

Após a conclusão bem-sucedida dessa carga de trabalho (com save_result()), esse status será atualizado automaticamente para DONE .


Fluxos de trabalho paralelos

Para tarefas clássicas que podem ser paralelizadas, use o @distribute_task decorador para definir os requisitos de computação necessários para executar uma tarefa. Comece relembrando o transpile_remote.py exemplo do tópico “Escreva seu primeiro programa em Qiskit Serverless ” com o código a seguir.

O código a seguir requer que você já tenha salvo suas credenciais.

./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

Neste exemplo, você decorou a função transpile_remote() com @distribute_task(target={"cpu": 1}). Quando executado, ele cria uma tarefa de trabalho paralelo assíncrono com um único núcleo de CPU e retorna com uma referência para rastrear o trabalho. Para obter o resultado, passe a referência para a função get() . Podemos usar isso para executar várias tarefas 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)

Explore diferentes configurações de tarefas

Você pode alocar de forma flexível a CPU, a GPU e a memória para suas tarefas por meio do site @distribute_task(). Para o Qiskit Serverless na IBM Quantum® Platform, cada programa é equipado com 16 núcleos de CPU e 32 GB de RAM, que podem ser alocados dinamicamente conforme necessário.

Os núcleos de CPU podem ser alocados como núcleos de CPU completos ou até mesmo alocações fracionárias, conforme mostrado a seguir.

A memória é alocada em número de bytes. Lembre-se de que há 1024 bytes em um kilobyte, 1024 kilobytes em um megabyte e 1024 megabytes em um gigabyte. Para alocar 2 GB de memória para seu trabalhador, você precisa alocar "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

Gerencie dados em todo o seu programa

O Qiskit Serverless permite que você gerencie arquivos no diretório /data em todos os seus programas. Isso inclui várias limitações:

  • Atualmente, somente os arquivos tar e h5 são suportados
  • Esse é apenas um armazenamento /data plano e não pode ter subdiretórios /data/folder/

A seguir, mostramos como fazer upload de arquivos. Certifique-se de ter feito a autenticação em Qiskit Serverless com sua conta IBM Quantum (consulte Carregar para Qiskit Serverless para obter instruções).

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"}'

Em seguida, você pode listar todos os arquivos em seu diretório data . Esses dados podem ser acessados por todos os programas.

serverless.files(function=transpile_remote_demo)

Output:

['classifier_name.pkl.tar', 'output.json.tar', 'transpile_demo.tar']

Isso pode ser feito em um programa usando file_download() para fazer o download do arquivo para o ambiente do programa e descompactando o 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()

Nesse ponto, seu programa pode interagir com os arquivos, como faria com um experimento local. file_upload() os arquivos file_download(), file_delete() e podem ser chamados a partir do seu experimento local ou do seu programa carregado, para um gerenciamento de dados consistente e flexível.


Próximas etapas

Recomendações
Esta página foi útil?
Relate um bug, erro de digitação ou solicite conteúdo no GitHub.