Vai al contenuto principale

Visualizza il timing del Circuit

Versioni dei pacchetti

Il codice in questa pagina è stato sviluppato con i seguenti requisiti. Ti consiglio di usare queste versioni o versioni più recenti.

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

Mentre il drawer timeline integrato in Qiskit è utile per i circuito statici, potrebbe non riflettere accuratamente il timing dei Circuit dinamici a causa di operazioni implicite come il broadcasting e la determinazione dei rami. Come parte del supporto ai Circuit dinamici, Qiskit Runtime restituisce le informazioni accurate sul timing del circuito all'interno dei risultati del job quando richiesto.

Note
  • Questa è una funzione sperimentale. È in stato di anteprima ed è quindi soggetta a modifiche.
  • Questa funzione si applica solo ai job Qiskit Runtime Sampler.
  • Sebbene il tempo totale del circuito venga restituito nei metadati di "compilation", questo NON è il tempo utilizzato per la fatturazione (tempo QPU).

Abilita il recupero dei dati di timing

Per abilitare il recupero dei dati di timing, imposta il flag sperimentale scheduler_timing su True quando esegui il job della 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()

Accedi ai dati di timing del circuito

Quando richiesti, i dati di timing del circuito per ogni PUB vengono restituiti nei metadati del risultato del job, sotto ["compilation"]["scheduler_timing"]["timing"]. Questo campo contiene le informazioni di timing non elaborate. Per visualizzare le informazioni di timing, usa lo strumento di visualizzazione integrato, come descritto nella sezione Visualizza i timing.

Usa il seguente codice per accedere ai dati di timing del circuito per il primo PUB:

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

Comprendi i dati di timing non elaborati

Sebbene la visualizzazione dei dati di timing del circuito tramite il metodo draw_circuit_schedule_timing sia il caso d'uso più comune, potrebbe essere utile comprendere la struttura dei dati di timing non elaborati restituiti. Questo potrebbe aiutarti, ad esempio, a estrarre informazioni a livello programmatico.

I dati di timing restituiti in ["compilation"]["scheduler_timing"]["timing"] sono un elenco di stringhe. Ogni stringa rappresenta una singola istruzione su qualche canale ed è separata da virgole nei seguenti tipi di dati:

  • Branch - Determina se l'istruzione è in un flusso di controllo (then / else) o un ramo principale.
  • Instruction - Il gate e il qubit su cui operare.
  • Channel - Il canale che viene assegnato con l'istruzione. Può essere uno dei seguenti:
    • qubit x - Il canale di drive per il qubit x.
    • AWGRx_y (generatore di forme d'onda arbitrarie readout) - Usato dai canali di readout per comunicare quando si misurano i qubit. Gli argomenti x e y corrispondono rispettivamente all'ID dello strumento di readout e al numero del qubit.
  • T0 - Il tempo di inizio dell'istruzione all'interno della pianificazione completa
  • Duration - La durata dell'istruzione, in unità di secondi dt, dove 1 dt = 1 ciclo di pianificazione. Puoi trovare il valore dt di un backend usando backend.dt.
  • Pulse - Il tipo di operazione di impulso in uso.

Esempio:

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

Visualizza i timing

Con qiskit-ibm-runtime v0.43.0 o versioni successive, puoi visualizzare i timing del circuito. Per visualizzare i timing, devi prima convertire i metadati del risultato in fig usando il metodo draw_circuit_schedule_timing. Questo metodo restituisce una figura plotly, che puoi visualizzare direttamente, salvare su file o entrambe. Per ulteriori informazioni sui comandi plotly da usare, consulta 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")

Passando il cursore sull&#39;output vengono mostrate informazioni come inizio, fine e durata.

Comprendi la figura generata

L'immagine dei dati di timing del circuito prodotta da draw_circuit_schedule_timing trasmette le seguenti informazioni:

  • L'asse X è il tempo in unità di secondi dt, dove 1 dt = 1 ciclo di pianificazione. Puoi trovare il valore dt di un backend usando backend.dt.
  • L'asse Y è il canale (i canali possono essere visti come strumenti che emettono impulsi).
    • Receive channel - L'unico canale che non è uno strumento di per sé. È un'istruzione riprodotta su tutti i canali che fanno parte di una procedura di comunicazione con l'hub in quel momento.
    • qubit x - Il canale di drive per il qubit x.
    • AWGRx_y (generatore di forme d'onda arbitrarie readout) - Usato dai canali di readout per comunicare quando si misurano i qubit. Gli argomenti x e y corrispondono rispettivamente all'ID dello strumento di readout e al numero del qubit.
    • Hub - Controlla il broadcasting.

Inoltre, ogni istruzione ha il formato X_Y, dove X è il nome dell'istruzione e Y è il tipo di impulso. Un tipo play applica impulsi di controllo e un capture registra lo stato del qubit. Puoi anche passare il cursore su ogni istruzione per ottenere ulteriori dettagli. Ad esempio, la figura precedente mostra un impulso di controllo per il gate X applicato al qubit 10 a 1161 dt.

Esempio end-to-end

Questo esempio mostra come abilitare l'opzione, ottenere le informazioni sul timing del circuito dai metadati e visualizzarle come immagine.

Prima, configura l'ambiente, definisci i circuito e convertili in Circuit ISA, e definisci ed esegui i job.

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)

Poi, ottieni il timing della pianificazione del 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'

Infine, puoi visualizzare e salvare il 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")

Passi successivi