Skip to main content
IBM Quantum Platform

Visualizar la sincronización del circuito

  • El código de esta página se ha desarrollado teniendo en cuenta los siguientes requisitos. Recomendamos utilizar estas versiones o posteriores.

    qiskit[all]~=2.5.0
    qiskit-ibm-runtime~=0.47.0
    

Aunque el diagrama de temporización integrado en Qiskit resulta útil para circuitos estáticos, es posible que no refleje con precisión la temporización de los circuitos dinámicos debido a operaciones implícitas como la difusión y la determinación de ramificaciones. Como parte de la compatibilidad con circuitos dinámicos, la función « Qiskit Runtime » devuelve información precisa sobre la sincronización del circuito en los resultados del trabajo cuando se solicita.

Notas
  • Esta es una función experimental. Se encuentra en fase de versión preliminar y, por lo tanto, está sujeta a cambios.
  • Esta función solo se aplica a los trabajos de muestreo de Qiskit Runtime.
  • Aunque el tiempo total de ejecución del circuito figura en los metadatos de «compilación», este NO es el tiempo que se utiliza para la facturación (tiempo de CPU).

Habilitar la recuperación de datos de sincronización

Para habilitar la recuperación de datos de tiempo, active el indicador scheduler_timing experimental al True ejecutar el trabajo primitivo.

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()

Acceder a los datos de tiempos del circuito

Cuando se solicita, los datos de tiempos del circuito para cada PUB se incluyen en los metadatos del resultado del trabajo, en ["compilation"]["scheduler_timing"]["timing"]la sección. Este campo contiene la información de sincronización sin procesar. Para visualizar la información de tiempos, utilice la herramienta de visualización integrada, tal y como se describe en la sección «Visualizar los tiempos ».

Utiliza el siguiente código para acceder a los datos de tiempos de la primera vuelta de « PUB »:

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

Comprender los datos de sincronización sin procesar

Aunque la visualización de los datos de temporización del circuito mediante este draw_circuit_schedule_timing método es el caso de uso más habitual, puede resultar útil comprender la estructura de los datos de temporización sin procesar que se devuelven. Esto podría ayudarte, por ejemplo, a extraer información mediante programación.

Los datos de tiempo devueltos en ["compilation"]["scheduler_timing"]["timing"] son una lista de cadenas. Cada cadena representa una única instrucción en un canal y está separada por comas en los siguientes tipos de datos:

  • Branch - Determina si la instrucción se encuentra en una rama de control (then / else) o en una rama principal.
  • Instruction - La puerta y el qubit sobre el que se va a operar.
  • Channel - El canal al que se le asigna la instrucción. Puede ser uno de los siguientes:
    • Qubit x - El canal de excitación del qubit x.
    • AWGRx_y (lectura del generador de formas de onda arbitrarias) - Utilizado por los canales de lectura para comunicarse durante la medición de qubits. Los argumentos x e y corresponden al identificador del instrumento de lectura y al número de qubit, respectivamente.
  • T0 - La hora de inicio de la clase dentro del horario completo
  • Duration - La duración de la instrucción, expresada en unidades de dt segundos, donde 1 dt = 1 ciclo de programación. Puedes averiguar el dt valor de un backend utilizando backend.dt.
  • Pulse - El tipo de funcionamiento por impulsos que se utiliza.

Ejemplo:

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

Visualiza los tiempos

Con qiskit-ibm-runtimev0.43.0 o una versión posterior, puedes visualizar los tiempos de los circuitos. Para visualizar los tiempos, primero debes convertir los metadatos del resultado a fig utilizando el draw_circuit_schedule_timing método. Este método devuelve una plotly figura, que puedes visualizar directamente, guardar en un archivo o ambas cosas. Para obtener más información sobre los plotly comandos que se deben utilizar, consulte fig.show() y 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")
Al pasar el cursor por encima del resultado, se muestra información como la hora de inicio, la hora de finalización y la duración.
Ejemplo de una figura generada

Entender la figura generada

La imagen de los datos de temporización del circuito generados por draw_circuit_schedule_timing ofrece la siguiente información:

  • El eje X representa el tiempo en unidades de dt segundos, donde 1 dt = 1 ciclo de programación. Puedes averiguar el dt valor de un backend utilizando backend.dt.
  • El eje Y representa el canal (piensa en los canales como instrumentos que emiten pulsos).
    • Receive channel - El único canal que no es un instrumento en sí mismo. Se trata de una instrucción que se transmite por todos los canales que forman parte de un procedimiento de comunicación con el concentrador en ese momento.
    • Qubit x - El canal de excitación del qubit x.
    • AWGRx_y (lectura del generador de formas de onda arbitrarias) - Utilizado por los canales de lectura para comunicarse durante la medición de qubits. Los argumentos x e y corresponden al identificador del instrumento de lectura y al número de qubit, respectivamente.
    • Hub - Controla la emisión.

Además, cada instrucción tiene el formato X_Y, donde X es el nombre de la instrucción y Y es el tipo de pulso. Uno aplica los impulsos play de control y el otro capture registra el estado del qubit. También puedes pasar el cursor por encima de cada instrucción para obtener más detalles. Por ejemplo, la figura anterior muestra un pulso de control para la puerta X aplicado al qubit 10 a los 1161 dt.

Ejemplo global

En este ejemplo se muestra cómo activar la opción, obtener la información de temporización del circuito a partir de los metadatos y mostrarla en forma de imagen.

En primer lugar, configura el entorno, define los circuitos y conviértelos a circuitos ISA, y define y ejecuta los trabajos.

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()})"
)

Output:

>>>  Job ID:    d9bk4smg26ic73dg33fg (DONE)

A continuación, consulta los horarios del circuito:

# Get the circuit schedule timing
result[0].metadata["compilation"]["scheduler_timing"]["timing"]

Output:

'main,rz_0,Qubit 0,897,0,shift_phase\nmain,sx_0,Qubit 0,897,6,play\nmain,sx_0,Qubit 0,901,0,shift_phase\nmain,rz_0,Qubit 0,903,0,shift_phase\nmain,barrier,Qubit 0,903,0,barrier\nmain,measure_0,Qubit 0,904,180,play\nmain,measure_0,AWGR0_0,1025,205,capture\nmain,barrier,Qubit 0,1431,0,barrier\nmain,broadcast,Hub,1025,406,broadcast\nmain,receive,Receive,1431,7,receive\nthen,x_0,Qubit 0,1446,6,play\nmain,barrier,Qubit 0,1460,0,barrier\nmain,measure_0,Qubit 0,1461,180,play\nmain,measure_0,AWGR0_0,1582,205,capture\nmain,barrier,Qubit 0,1886,0,barrier\nmain,barrier,Qubit 0,1886,0,barrier\nmain,FINI_0,Qubit 0,1887,180,play\nmain,FINI_0,AWGR0_0,2008,205,capture\nmain,FINI_0,Qubit 0,2312,6,play\nmain,FINI_0,Qubit 0,2319,180,play\nmain,FINI_0,AWGR0_0,2440,205,capture\nmain,FINI_0,Qubit 0,2744,6,play\nmain,barrier,Qubit 0,2750,0,barrier\n'

Por último, puedes visualizar y guardar la sincronización:

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 pasos

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