Skip to content

Commit

Permalink
Gen telemetry info (#25)
Browse files Browse the repository at this point in the history
## Resume
Related to #19 
- Generate the telemetry info about the job running in the Runtime.

## Details
- [x] Add gen_telemetry.py function to generate the file
- [x] Add it to the kernel controller
- [x] Get job id from run_sampler.py
- [x] Get times info (queue vs simu)
- [x] Get size of the payload
- [x] Add view_telemetry endpoint as cli
- [x] Add unittests
- [x] Edit requirements
  • Loading branch information
mickahell authored Apr 16, 2022
1 parent de8bbde commit 33613e7
Show file tree
Hide file tree
Showing 15 changed files with 240 additions and 58 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/gen-metadata.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ jobs:
env:
QS_TOKEN: ${{ secrets.QUANTUM_SERVICES_TOKEN }}
run: |
python worflow.py authentication --auth="legacy" --token="${QS_TOKEN}" --instance="ibm-q/open/main"
python workflow.py authentication --channel="ibm_quantum" --token="${QS_TOKEN}" --instance="ibm-q/open/main"
- name: Generate metadata
env:
CIRCUIT_ID: ${{ github.event.inputs.circuit_id }}
Expand All @@ -61,7 +61,7 @@ jobs:
LAYER: ${{ github.event.inputs.layer }}
BACKEND: ${{ github.event.inputs.backend }}
run: |
python worflow.py kernel_flow --circuit_tpl_id=[${CIRCUIT_ID}] --width=${NB_QUBITS} --layer=${LAYER} --matrix_size=[${MATRIX_SIZE},${MATRIX_SIZE}] --backend="${BACKEND}" --shots=${SHOTS}
python workflow.py kernel_flow --circuit_tpl_id=[${CIRCUIT_ID}] --width=${NB_QUBITS} --layer=${LAYER} --matrix_size=[${MATRIX_SIZE},${MATRIX_SIZE}] --backend="${BACKEND}" --shots=${SHOTS}
- name: Pull modif
run: git pull
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ fire==0.4.0
qiskit
qiskit_ibm_runtime
pandas==1.4.1
pyarrow
pyarrow==7.0.0
Binary file modified resources/kernel_metadata/ibmq_qasm_simulator/kernels-10-ideal.csv
Binary file not shown.
Binary file added resources/kernel_metadata/telemetry_info.csv
Binary file not shown.
14 changes: 12 additions & 2 deletions src/controllers/kernel.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import sys

from src.circuits import circuit_2, circuit_5, circuit_10, circuit_18, kernel_circuit
from src.data import kernel_metadata
from src.data import kernel_metadata, kernel_telemetry
from src.runtime import run_sampler


Expand Down Expand Up @@ -107,7 +107,7 @@ def kernel_endpoint(
circuits_tpl=circuits_tpl, seed_x=seed_x, seed_y=seed_y, verbose=verbose
)

run = run_sampler(
run, telemetry_info = run_sampler(
circuits=kernel_cirq, backend=backend, shots=shots, verbose=verbose
)

Expand All @@ -116,6 +116,16 @@ def kernel_endpoint(
"::set-output name={name}::{value}".format(name="KernelResult", value=run)
)

kernel_telemetry(
circuit_tpl_id=circuit_tpl_id,
job_id=telemetry_info[0],
time_queue=float(telemetry_info[1]),
time_simu=float(telemetry_info[2]),
payload_size=sys.getsizeof(kernel_cirq),
width=width,
layer=layer,
)

return kernel_metadata(
circuit_tpl_id=circuit_tpl_id,
width=width,
Expand Down
1 change: 1 addition & 0 deletions src/data/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"""Data functions and classes."""

from .gen_data import kernel_metadata
from .gen_telemetry import kernel_telemetry
17 changes: 9 additions & 8 deletions src/data/gen_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@

import os
import pandas as pd
from qiskit_ibm_runtime import SamplerResult


def kernel_metadata(
Expand All @@ -22,7 +21,7 @@ def kernel_metadata(
seed1: [int],
seed2: [int],
backend: str,
runtime_result: SamplerResult,
runtime_result: dict,
) -> [str]:
"""Function generate kernel metadata files.
Expand All @@ -48,14 +47,16 @@ def kernel_metadata(
for circ_index, circuit in enumerate(circuit_tpl_id):
fidelity = []
min_lim = int(
circ_index * len(runtime_result.quasi_dists) / len(circuit_tpl_id)
circ_index * len(runtime_result["quasi_dists"]) / len(circuit_tpl_id)
)
max_lim = int(
len(runtime_result["quasi_dists"]) / len(circuit_tpl_id) + min_lim
)
max_lim = int(len(runtime_result.quasi_dists) / len(circuit_tpl_id) + min_lim)
for i in range(min_lim, max_lim):
if runtime_result.quasi_dists[i].get(wanted_result) is not None:
fidelity.append(runtime_result.quasi_dists[i][wanted_result])
elif runtime_result.quasi_dists[i].get("0") is not None:
fidelity.append(runtime_result.quasi_dists[i]["0"])
if runtime_result["quasi_dists"][i].get(wanted_result) is not None:
fidelity.append(runtime_result["quasi_dists"][i][wanted_result])
elif runtime_result["quasi_dists"][i].get("0") is not None:
fidelity.append(runtime_result["quasi_dists"][i]["0"])
else:
fidelity.append(0)

Expand Down
82 changes: 82 additions & 0 deletions src/data/gen_telemetry.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
"""
#############################################
#
# gen_telemetry.py
#
# program to generate telemetry
#
#
#############################################
"""

import os
import pandas as pd


def kernel_telemetry(
circuit_tpl_id: [int],
job_id: str,
time_queue: float,
time_simu: float,
payload_size: int,
width: int,
layer: int,
) -> str:
"""Function generate telemetry metadata files.
Args:
circuit_tpl_id: list of circuit id to run as template
job_id: id of the experiment
time_queue: time stuck in the queue
time_simu: duration of running everything
payload_size: size of the payload send into the Runtime
width: number of qubits
layer: number of reps for the tpl
Returns:
Telemetry file name
"""
data_name = "telemetry_info.csv"
current_dir = os.path.dirname(os.path.abspath(__file__))
dest = "../../resources/kernel_metadata"
if os.path.exists("{}/{}/{}".format(current_dir, dest, data_name)):
old_file = pd.read_feather("{}/{}/{}".format(current_dir, dest, data_name))

list_width = old_file["width"].tolist()
list_width.append(width)
list_layers = old_file["layers"].tolist()
list_layers.append(layer)
list_circuit_id = old_file["circuit_id"].tolist()
list_circuit_id.append(str(circuit_tpl_id))
list_job_id = old_file["job_id"].tolist()
list_job_id.append(job_id)
list_time_queue = old_file["time_queue"].tolist()
list_time_queue.append(time_queue)
list_time_simu = old_file["time_simu"].tolist()
list_time_simu.append(time_simu)
list_payload_size = old_file["payload_size"].tolist()
list_payload_size.append(payload_size)
else:
list_width = [width]
list_layers = [layer]
list_circuit_id = [str(circuit_tpl_id)]
list_job_id = [job_id]
list_time_queue = [time_queue]
list_time_simu = [time_simu]
list_payload_size = [payload_size]

fea_file = {
"width": list_width,
"layers": list_layers,
"circuit_id": list_circuit_id,
"job_id": list_job_id,
"time_queue": list_time_queue,
"time_simu": list_time_simu,
"payload_size": list_payload_size,
}

data_fea = pd.DataFrame(fea_file)

data_fea.to_feather("{}/{}/".format(current_dir, dest) + data_name)

return data_name
44 changes: 34 additions & 10 deletions src/runtime/run_sampler.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,16 @@
#
#############################################
"""
from typing import Tuple
from time import time

from qiskit_ibm_runtime import IBMRuntimeService, IBMSampler, SamplerResult
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit import QuantumCircuit


def run_sampler(
circuits: [QuantumCircuit], backend="ibmq_qasm_simulator", shots=1024, verbose=False
) -> SamplerResult:
) -> Tuple[dict, list]:
"""Function to run the final circuit on quantum computer.
Args:
Expand All @@ -25,18 +27,40 @@ def run_sampler(
verbose: True/False
Return:
Result from the running
Result from the running + telemetry info
"""
if backend != "simulator_statevector":
for cirq in circuits:
cirq.measure_all()

service = IBMRuntimeService()
sampler_factory = IBMSampler(service=service, backend=backend)
service = QiskitRuntimeService()
program_inputs = {
"circuits": circuits,
"circuit_indices": list(range(len(circuits))),
"run_options": {"shots": shots},
}

with sampler_factory(circuits=circuits) as sampler:
result = sampler(circuit_indices=list(range(len(circuits))), shots=shots)
if verbose:
print(result)
options = {"backend_name": backend}

return result
start_time = time()

job = service.run(
program_id="sampler",
options=options,
inputs=program_inputs,
)

while str(job.status()) == "JobStatus.QUEUED":
pass
time_queue = time() - start_time
while str(job.status()) == "JobStatus.RUNNING":
pass

result = job.result()
time_simu = time() - time_queue - start_time

if verbose:
print(result)

telemetry_info = [job.job_id, time_queue, time_simu]
return result, telemetry_info
37 changes: 31 additions & 6 deletions src/workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from typing import List

import pandas as pd
from qiskit_ibm_runtime import IBMRuntimeService
from qiskit_ibm_runtime import QiskitRuntimeService

from src.controllers import kernel_endpoint

Expand All @@ -17,29 +17,31 @@ class Workflow:
Each public method of this class is CLI command
and arguments for method are options/flags for this command.
Ex: `python worflow.py kernel_flow --circuit_tpl_id=[2,5]`
Ex: `python workflow.py kernel_flow --circuit_tpl_id=[2,5]`
"""

def __init__(self):
pass

@staticmethod
def authentication(
auth: str, token: str, instance="ibm-q/open/main", overwrite=False
channel: str, token: str, instance="ibm-q/open/main", overwrite=False
) -> None:
"""Commands for authentication.
Args:
auth: if you have a Cloud account : "cloud", is you have an Quantum account "legacy"
channel:
if you have a Cloud account : "ibm_cloud",
if you have an Quantum account "ibm_quantum"
token: your IBM Cloud/Quantum token
instance: group path for computer access
overwrite: set True if you want to overwrite your actual token
Return:
Register the session in disk space
"""
IBMRuntimeService.save_account(
auth=auth, token=token, instance=instance, overwrite=overwrite
QiskitRuntimeService.save_account(
channel=channel, token=token, instance=instance, overwrite=overwrite
)

@staticmethod
Expand Down Expand Up @@ -126,3 +128,26 @@ def view_kernel(
)

return data_fea

@staticmethod
def view_telemetry(file_name: str = "telemetry_info.csv") -> pd.DataFrame:
"""Commands for decode telemetry files.
Args:
file_name: name of the file to decode in resources/kernel_metadata
Return:
Return file_name decode as pandas.Dataframe
"""
local = "../resources/kernel_metadata/"
current_dir = os.path.dirname(os.path.abspath(__file__))

data_fea = pd.read_feather("{}/{}/".format(current_dir, local) + file_name)

print(
"::set-output name={name}::{value}".format(
name=file_name, value="\n" + str(data_fea)
)
)

return data_fea
40 changes: 32 additions & 8 deletions tests/data/test_gen_data.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
"""Tests for data."""
import sys
from typing import List
from unittest import TestCase
from src.data import kernel_metadata
from src.data import kernel_metadata, kernel_telemetry
from src.controllers import gen_kernel_circuits, gen_circuits_tpl
from tests.runtime import return_sampler


Expand All @@ -10,13 +12,13 @@ class TestUtils(TestCase):

def test_kernel_metadata(self):
"""Test to test the kernel metadata function."""
re_sampler = return_sampler.get_sampler()
circuits_2 = list(range(901, 901 + int(len(re_sampler.quasi_dists) / 2)))
re_sampler, _ = return_sampler.get_sampler()
circuits_2 = list(range(901, 901 + int(len(re_sampler["quasi_dists"]) / 2)))
seed_x_2 = [
42 for i in range(int(len(re_sampler.quasi_dists) / len(circuits_2)))
42 for _ in range(int(len(re_sampler["quasi_dists"]) / len(circuits_2)))
]
seed_y_2 = [
4242 for i in range(int(len(re_sampler.quasi_dists) / len(circuits_2)))
4242 for _ in range(int(len(re_sampler["quasi_dists"]) / len(circuits_2)))
]

fea_files_2 = kernel_metadata(
Expand All @@ -31,12 +33,12 @@ def test_kernel_metadata(self):
)
self.assertTrue(isinstance(fea_files_2, List))

circuits_3 = list(range(901, 901 + int(len(re_sampler.quasi_dists) / 3)))
circuits_3 = list(range(901, 901 + int(len(re_sampler["quasi_dists"]) / 3)))
seed_x_3 = [
42 for i in range(int(len(re_sampler.quasi_dists) / len(circuits_3)))
42 for _ in range(int(len(re_sampler["quasi_dists"]) / len(circuits_3)))
]
seed_y_3 = [
4242 for i in range(int(len(re_sampler.quasi_dists) / len(circuits_3)))
4242 for _ in range(int(len(re_sampler["quasi_dists"]) / len(circuits_3)))
]

fea_files_3 = kernel_metadata(
Expand All @@ -50,3 +52,25 @@ def test_kernel_metadata(self):
runtime_result=re_sampler,
)
self.assertTrue(isinstance(fea_files_3, List))

def test_kernel_telemetry(self):
"""Test to test the kernel telemetry function."""
circuits_tpl = gen_circuits_tpl(circuit_tpl_id=[2], width=4, layer=1)
kernel_cirq = gen_kernel_circuits(
circuits_tpl=circuits_tpl, seed_x=[0, 1, 1], seed_y=[0, 0, 1]
)

_, te_sampler = return_sampler.get_sampler()

print("Tele : ", te_sampler)

fea_files = kernel_telemetry(
circuit_tpl_id=[2],
job_id=te_sampler[0],
time_queue=float(te_sampler[1]),
time_simu=float(te_sampler[2]),
payload_size=sys.getsizeof(kernel_cirq),
width=4,
layer=1,
)
self.assertTrue(isinstance(fea_files, str))
Loading

0 comments on commit 33613e7

Please sign in to comment.