Pular para o conteúdo principal

Visualizar o timing do Circuit

Versões dos pacotes

O código desta página foi desenvolvido usando os seguintes requisitos. Recomendamos usar essas versões ou versões mais recentes.

qiskit[all]~=2.4.0
qiskit-ibm-runtime~=0.46.1

Embora o visualizador de linha do tempo integrado ao Qiskit seja útil para Circuits estáticos, ele pode não refletir com precisão o timing de Circuits dinâmicos por causa de operações implícitas como broadcasting e determinação de branch. Como parte do suporte a Circuits dinâmicos, o Qiskit Runtime retorna as informações precisas de timing do circuito nos resultados do job quando solicitado.

Notas
  • Esta é uma função experimental. Está em status de versão prévia e, portanto, sujeita a alterações.
  • Esta função aplica-se apenas a jobs do Sampler do Qiskit Runtime.
  • Embora o tempo total do circuito seja retornado nos metadados de "compilação", este NÃO é o tempo usado para cobrança (tempo de QPU).

Habilitar a recuperação de dados de timing

Para habilitar a recuperação de dados de timing, defina o sinalizador experimental scheduler_timing como True ao executar o job da primitiva.

# Added by doQumentation — required packages for this notebook
!pip install -q qiskit qiskit-ibm-runtime
from qiskit import QuantumCircuit
from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2
from qiskit.transpiler import generate_preset_pass_manager

service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False)

qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)
qc.measure_all()

pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_circuit = pm.run(qc)

sampler = SamplerV2(backend)
sampler.options.experimental = {
"execution": {
"scheduler_timing": True,
},
}

sampler_job = sampler.run([isa_circuit])
result = sampler_job.result()

Acessar os dados de timing do circuito

Quando solicitados, os dados de timing do circuito para cada PUB são retornados nos metadados do resultado do job, em ["compilation"]["scheduler_timing"]["timing"]. Este campo contém as informações brutas de timing. Para exibir as informações de timing, use a ferramenta de visualização integrada, conforme descrito na seção Visualizar os timings.

Use o código a seguir para acessar os dados de timing do circuito para o primeiro PUB:

job_result = sampler_job.result()
circuit_schedule = job_result[0].metadata["compilation"]["scheduler_timing"]
circuit_schedule_timing = circuit_schedule["timing"]

Entender os dados brutos de timing

Embora visualizar os dados de timing do circuito usando o método draw_circuit_schedule_timing seja o caso de uso mais comum, pode ser útil entender a estrutura dos dados brutos de timing retornados. Isso pode ajudá-lo, por exemplo, a extrair informações programaticamente.

Os dados de timing retornados em ["compilation"]["scheduler_timing"]["timing"] são uma lista de strings. Cada string representa uma única instrução em algum canal e é separada por vírgulas nos seguintes tipos de dados:

  • Branch - Determina se a instrução está em um fluxo de controle (then / else) ou em um branch principal.
  • Instruction - O gate e o qubit a operar.
  • Channel - O canal que está sendo atribuído com a instrução. Pode ser um dos seguintes:
    • qubit x - O canal de drive para o qubit x.
    • AWGRx_y (gerador de forma de onda arbitrária de leitura) - Usado por canais de leitura para comunicar quando medir qubits. Os argumentos x e y correspondem ao ID do instrumento de leitura e ao número do qubit, respectivamente.
  • T0 - O tempo de início da instrução dentro do agendamento completo
  • Duration - A duração da instrução, em unidades de dt segundos, onde 1 dt = 1 ciclo de agendamento. Você pode encontrar o valor dt de um Backend usando backend.dt.
  • Pulse - O tipo de operação de pulso sendo usado.

Exemplo:

main,barrier,Qubit 0,7,0,barrier # A barrier on the main branch on qubit 0 at time 7 with 0 duration
main,reset_0,Qubit 0,7,64,play # A reset instruction on the main branch on qubit 0 at time 7 with duration 64 and a play operation
...

Visualizar os timings

Com o qiskit-ibm-runtime v0.43.0 ou posterior, você pode visualizar os timings de circuito. Para visualizar os timings, você primeiro precisa converter os metadados do resultado para fig usando o método draw_circuit_schedule_timing. Este método retorna uma figura plotly, que você pode exibir diretamente, salvar em um arquivo ou ambos. Para mais informações sobre os comandos plotly a usar, veja fig.show() e fig.write_image("<path.format>").

from qiskit_ibm_runtime.visualization import draw_circuit_schedule_timing

# Create a figure from the metadata
fig = draw_circuit_schedule_timing(
circuit_schedule=circuit_schedule_timing,
included_channels=None,
filter_readout_channels=False,
filter_barriers=False,
width=1000,
)

# Uncomment the following line to display the figure
# fig.show(renderer="notebook")

# Save to a file
# fig.write_html("scheduler_timing.html")

Passar o mouse sobre a saída mostra informações como início, fim e duração.

Entender a figura gerada

A imagem dos dados de timing do circuito gerada por draw_circuit_schedule_timing transmite as seguintes informações:

  • O eixo X é o tempo em unidades de dt segundos, onde 1 dt = 1 ciclo de agendamento. Você pode encontrar o valor dt de um Backend usando backend.dt.
  • O eixo Y é o canal (pense nos canais como instrumentos que emitem pulsos).
    • Receive channel - O único canal que não é um instrumento em si. É uma instrução executada em todos os canais que fazem parte de um procedimento de comunicação com o hub naquele momento.
    • qubit x - O canal de drive para o qubit x.
    • AWGRx_y (gerador de forma de onda arbitrária de leitura) - Usado por canais de leitura para comunicar quando medir qubits. Os argumentos x e y correspondem ao ID do instrumento de leitura e ao número do qubit, respectivamente.
    • Hub - Controla o broadcasting.

Adicionalmente, cada instrução tem o formato X_Y, onde X é o nome da instrução e Y é o tipo de pulso. Um tipo play aplica pulsos de controle e um capture registra o estado do qubit. Você também pode passar o mouse sobre cada instrução para obter mais detalhes. Por exemplo, a figura anterior mostra um pulso de controle para o gate X aplicado ao qubit 10 em 1161 dt.

Exemplo de ponta a ponta

Este exemplo mostra como habilitar a opção, obter as informações de timing do circuito dos metadados e exibi-las como uma imagem.

Primeiro, configure o ambiente, defina os circuitos e converta-os para Circuits ISA, e defina e execute os jobs.

from qiskit_ibm_runtime import SamplerV2, QiskitRuntimeService
from qiskit.circuit import QuantumCircuit, QuantumRegister, ClassicalRegister
from qiskit.transpiler import generate_preset_pass_manager

service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False)

# Create a dynamic circuit

qubits = QuantumRegister(1)
clbits = ClassicalRegister(1)
qc = QuantumCircuit(qubits, clbits)
(q0,) = qubits
(c0,) = clbits

qc.h(q0)
qc.measure(q0, c0)
with qc.if_test((c0, 1)):
qc.x(q0)
qc.measure(q0, c0)

# Convert to an ISA circuit for the given backend

pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_circuit = pm.run(qc)

# Generate samplers for backend targets
sampler = SamplerV2(backend)
sampler.options.experimental = {"execution": {"scheduler_timing": True}}

# Submit jobs
sampler_job = sampler.run([isa_circuit])
result = sampler_job.result()

print(
f">>> {' Job ID:':<10} {sampler_job.job_id()} ({sampler_job.status()})"
)
>>> Job ID: d8287kugbeec73alfbug (DONE)

Em seguida, obtenha o timing do agendamento do circuito:

# Get the circuit schedule timing
result[0].metadata["compilation"]["scheduler_timing"]["timing"]
'main,rz_0,Qubit 0,1365,0,shift_phase\nmain,sx_0,Qubit 0,1365,9,play\nmain,sx_0,Qubit 0,1369,0,shift_phase\nmain,rz_0,Qubit 0,1374,0,shift_phase\nmain,barrier,Qubit 0,1374,0,barrier\nmain,measure_0,Qubit 0,1374,64,play\nmain,measure_0,Qubit 0,1438,108,play\nmain,measure_0,AWGR0_0,1485,360,capture\nmain,measure_0,Qubit 0,1546,64,play\nmain,measure_0,Qubit 0,1610,64,play\nmain,barrier,Qubit 0,2046,0,barrier\nmain,broadcast,Hub,1485,561,broadcast\nmain,receive,Receive,2046,7,receive\nthen,x_0,Qubit 0,2061,9,play\nmain,barrier,Qubit 0,2079,0,barrier\nmain,measure_0,Qubit 0,2079,64,play\nmain,measure_0,Qubit 0,2143,108,play\nmain,measure_0,AWGR0_0,2190,360,capture\nmain,measure_0,Qubit 0,2251,64,play\nmain,measure_0,Qubit 0,2315,64,play\nmain,barrier,Qubit 0,2725,0,barrier\nmain,barrier,Qubit 0,2725,0,barrier\n'

Por fim, você pode visualizar e salvar o timing:

from qiskit_ibm_runtime.visualization import draw_circuit_schedule_timing

circuit_schedule = result[0].metadata["compilation"]["scheduler_timing"][
"timing"
]
fig = draw_circuit_schedule_timing(
circuit_schedule=circuit_schedule,
included_channels=None,
filter_readout_channels=False,
filter_barriers=False,
width=1000,
)

# Uncomment the following line to display the figure
# fig.show(renderer="notebook")

# Save to a file
# fig.write_html("scheduler_timing.html")

Próximos passos