Przejdź do głównej treści
Ten projekt jest w wersji beta. Znalazłeś błąd? Otwórz zgłoszenie na GitHub. Masz pytanie lub pomysł? Zapytaj w Discussions — chętnie poznamy Twoją opinię!
Jak oceniasz jakość tłumaczenia tej strony?

Wizualizacja czasu wykonania obwodu

Wersje pakietów

Kod na tej stronie został opracowany przy użyciu następujących wymagań. Zalecamy używanie tych lub nowszych wersji.

qiskit[all]~=2.6.1
qiskit-ibm-runtime~=0.50.0

Chociaż rysownik osi czasu wbudowany w Qiskit jest przydatny dla statycznych obwodów, może nie dokładnie odzwierciedlać czasu wykonania obwodów dynamicznych ze względu na niejawne operacje, takie jak rozgłaszanie i określanie gałęzi. W ramach obsługi obwodów dynamicznych IBM Quantum Compute Service zwraca dokładne informacje o czasie wykonania obwodu wewnątrz wyników zadania, gdy jest to wymagane.

Uwagi
  • Jest to funkcja eksperymentalna. Jest w fazie wersji zapoznawczej i dlatego może ulec zmianie.
  • Ta funkcja dotyczy tylko zadań IBM Quantum Sampler i Executor.
  • Chociaż całkowity czas obwodu jest zwracany w metadanych "compilation", NIE jest to czas używany do rozliczeń (czas QPU).
wskazówka

Ta opcja działa również z zadaniami dry-run. Przekaż dry_run=True do run(), aby uzyskać harmonogram czasowy obwodu bez zużywania czasu QPU.

Włączanie pobierania danych czasowych​

Aby włączyć pobieranie danych czasowych, ustaw eksperymentalną flagę scheduler_timing na True podczas uruchamiania zadania prymitywu.

# Added by doQumentation — installs the packages this notebook needs if they are missing
import importlib.util

_needed = {"qiskit": "qiskit", "qiskit_ibm_runtime": "qiskit-ibm-runtime"}
_missing = [pip for module, pip in _needed.items()
if importlib.util.find_spec(module) is None]
# One at a time, so a package that fails to install does not block the others
for _pip in _missing:
%pip install -q {_pip}
if not _missing:
print("\u2713 All required packages are installed")
from qiskit import QuantumCircuit
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit.transpiler import generate_preset_pass_manager

# Legacy server-side primitive before qiskit-ibm-runtime v0.50.0
# from qiskit_ibm_runtime import Sampler

# Client-side primitive introduced in qiskit-ibm-runtime v0.50.0
from qiskit_ibm_runtime.executor_sampler import Sampler

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 = Sampler(backend)
sampler.options.experimental = {
"execution": {
"scheduler_timing": True,
},
}

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

Dostęp do danych czasowych obwodu​

Gdy jest to wymagane, dane czasowe obwodu dla każdego PUB są zwracane w metadanych wynikowych zadania, pod ["compilation"]["scheduler_timing"]["timing"]. To pole zawiera surowe informacje o czasie. Aby wyświetlić informacje o czasie, użyj wbudowanego narzędzia wizualizacji, jak opisano w sekcji Wizualizacja czasów.

Użyj poniższego kodu, aby uzyskać dostęp do danych czasowych obwodu dla pierwszego PUB:

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

Zrozumienie surowych danych czasowych​

Chociaż wizualizacja danych czasowych obwodu za pomocą metody draw_circuit_schedule_timing jest najczęstszym przypadkiem użycia, może być przydatne zrozumienie struktury zwracanych surowych danych czasowych. Może to pomóc, na przykład, w programowym wyodrębnianiu informacji.

Dane czasowe zwracane w ["compilation"]["scheduler_timing"]["timing"] to lista ciągów znaków. Każdy ciąg reprezentuje pojedynczą instrukcję na jakimś kanale i jest rozdzielony przecinkami na następujące typy danych:

  • Branch - Określa, czy instrukcja jest w przepływie sterowania (then / else) czy w gałęzi głównej.

  • Instruction - Bramka i kubit, na którym ma działać.

  • Channel - Kanał, do którego przypisana jest instrukcja. Może być jednym z następujących:

    • Qubit x - Kanał sterowania dla kubitu x.

    • AWGRx_y (generator dowolnych przebiegów do odczytu) - Używany przez kanały odczytu do komunikacji podczas pomiaru kubitów. Argumenty x i y odpowiadają odpowiednio identyfikatorowi instrumentu odczytu i numerowi kubitu.

  • T0 - Czas rozpoczęcia instrukcji w pełnym harmonogramie

  • Duration - Czas trwania instrukcji, w jednostkach dt sekund, gdzie 1 dt = 1 cykl harmonogramowania. Wartość dt backendu można znaleźć za pomocą backend.dt.

  • Pulse - Typ używanej operacji impulsowej.

Przykład:

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

Wizualizacja czasów​

W wersji qiskit-ibm-runtime v0.43.0 lub nowszej możesz wizualizować czasy obwodów. Aby zwizualizować czasy, musisz najpierw przekonwertować metadane wynikowe na fig za pomocą metody draw_circuit_schedule_timing. Ta metoda zwraca figurę plotly, którą możesz wyświetlić bezpośrednio, zapisać do pliku lub zrobić jedno i drugie. Aby uzyskać więcej informacji o poleceniach plotly, zobacz fig.show() i 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")

Hovering over the output shows information such as the start, finish, and duration.

Zrozumienie wygenerowanej figury​

Obraz wyjściowy danych czasowych obwodu generowany przez draw_circuit_schedule_timing przekazuje następujące informacje:

  • Oś X to czas w jednostkach dt sekund, gdzie 1 dt = 1 cykl harmonogramowania. Wartość dt backendu można znaleźć za pomocą backend.dt.

  • Oś Y to kanał (kanały można traktować jako instrumenty emitujące impulsy).

    • Receive channel - Jedyny kanał, który sam w sobie nie jest instrumentem. Jest to instrukcja odtwarzana na wszystkich kanałach, które są częścią procedury komunikacji z centrum w danym czasie.

    • Qubit x - Kanał sterowania dla kubitu x.

    • AWGRx_y (generator dowolnych przebiegów do odczytu) - Używany przez kanały odczytu do komunikacji podczas pomiaru kubitów. Argumenty x i y odpowiadają odpowiednio identyfikatorowi instrumentu odczytu i numerowi kubitu.

    • Hub - Kontroluje rozgłaszanie.

Ponadto każda instrukcja ma format X_Y, gdzie X to nazwa instrukcji, a Y to typ impulsu. Typ play stosuje impulsy sterujące, a capture rejestruje stan kubitu. Możesz również najechać kursorem na każdą instrukcję, aby uzyskać więcej szczegółów. Na przykład poprzednia figura pokazuje impuls sterujący dla bramki X zastosowany do kubitu 10 w czasie 1161 dt.

Przykład end-to-end​

Ten przykład pokazuje, jak włączyć opcję, uzyskać informacje o czasie obwodu z metadanych i wyświetlić je jako obraz.

Najpierw skonfiguruj środowisko, zdefiniuj obwody i przekonwertuj je na obwody ISA, a następnie zdefiniuj i uruchom zadania.

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

# Legacy server-side primitive before qiskit-ibm-runtime v0.50.0
# from qiskit_ibm_runtime import Sampler

# Client-side primitive introduced in qiskit-ibm-runtime v0.50.0
from qiskit_ibm_runtime.executor_sampler import Sampler

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 = Sampler(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: dbjed5pkdqps7390ev00 (DONE)

Następnie pobierz harmonogram czasu obwodu:

# Get the circuit schedule timing
result[0].metadata["compilation"]["scheduler_timing"]["timing"]
'main,rz_0,Qubit 0,875,0,shift_phase\nmain,sx_0,Qubit 0,875,6,play\nmain,sx_0,Qubit 0,879,0,shift_phase\nmain,rz_0,Qubit 0,882,0,shift_phase\nmain,barrier,Qubit 0,882,0,barrier\nmain,measure_0,Qubit 0,882,180,play\nmain,measure_0,AWGR0_0,1003,205,capture\nmain,barrier,Qubit 0,1409,0,barrier\nmain,broadcast,Hub,1003,406,broadcast\nmain,receive,Receive,1409,7,receive\nthen,x_0,Qubit 0,1424,6,play\nmain,barrier,Qubit 0,1437,0,barrier\nmain,measure_0,Qubit 0,1437,180,play\nmain,measure_0,AWGR0_0,1558,205,capture\nmain,barrier,Qubit 0,1852,0,barrier\nmain,barrier,Qubit 0,1852,0,barrier\nmain,FINI_0,Qubit 0,1852,180,play\nmain,FINI_0,AWGR0_0,1973,205,capture\nmain,FINI_0,Qubit 0,2267,6,play\nmain,FINI_0,Qubit 0,2273,180,play\nmain,FINI_0,AWGR0_0,2394,205,capture\nmain,FINI_0,Qubit 0,2688,6,play\nmain,barrier,Qubit 0,2694,0,barrier\n'

Na koniec możesz zwizualizować i zapisać czas:

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

Następne kroki​