final first commit

This commit is contained in:
2026-05-19 17:19:36 +08:00
commit b199e2105e
114 changed files with 6844 additions and 0 deletions

View File

View File

@@ -0,0 +1,249 @@
"""Generates bar plots for qibojit breakdowns and multigpu comparisons."""
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import seaborn as sns
from matplotlib.patches import Patch
matplotlib.rcParams['mathtext.fontset'] = 'cm'
matplotlib.rcParams['font.family'] = 'STIXGeneral'
def plot_breakdown_nqubits(data, circuit, precision="double", width=0.1, fontsize=30, save=False):
"""Creates dry run vs simulation barplot with import time breakdown for given circuit varying the number of qubits."""
matplotlib.rcParams["font.size"] = fontsize
# Set plot params
hatches = ['/', '\\', 'o', '-', 'x', '.', '*']
quantities = ["import_time", "creation_time", "dry_run_time", "simulation_times_mean"]
nqubits = [22, 24, 26, 28, 30]
widths = [-5 * width / 2, - 3 * width / 2, -width / 2, width / 2, 3 * width / 2, 5 * width / 2]
oranges = sns.color_palette("Oranges", 2)
purples = sns.color_palette("Purples", 2)
greens = sns.color_palette("Greens", 2)
greys = sns.color_palette("Greys", 2)
# Plot the results
plt.figure(figsize=(25, 9))
plt.title(f"qibojit - Dry run vs simulation - {circuit}")
xvalues = np.array(range(len(nqubits)))
plt.xticks(xvalues, nqubits)
base_condition = ((data["precision"] == precision) & (data["circuit"] == circuit))
condition = base_condition & (data["library_options"] == "backend=qibojit,platform=numba")
heights_numba = {q: np.array([float(data[condition & (data["nqubits"] == n)][q]) for n in nqubits])
for q in quantities}
condition = base_condition & (data["library_options"] == "backend=qibojit,platform=cupy")
heights_cupy = {q: np.array([float(data[condition & (data["nqubits"] == n)][q]) for n in nqubits])
for q in quantities}
condition = base_condition & (data["library_options"] == "backend=qibojit,platform=cuquantum")
heights_cuquantum = {q: np.array([float(data[condition & (data["nqubits"] == n)][q]) for n in nqubits])
for q in quantities}
plt.bar(xvalues + widths[0], heights_numba["import_time"],
color=greys[0], align="center", width=width, alpha=1, hatch=hatches[0],
edgecolor='w')
plt.bar(xvalues + widths[1], heights_numba["import_time"],
color=greys[1], align="center", width=width, alpha=1, hatch=hatches[1],
edgecolor='w')
plt.bar(xvalues + widths[2], heights_cupy["import_time"],
color=greys[0], align="center", width=width, alpha=1, hatch=hatches[0],
edgecolor='w')
plt.bar(xvalues + widths[3], heights_cupy["import_time"],
color=greys[1], align="center", width=width, alpha=1, hatch=hatches[1],
edgecolor='w')
plt.bar(xvalues + widths[4], heights_cuquantum["import_time"],
color=greys[0], align="center", width=width, alpha=1, hatch=hatches[0],
edgecolor='w')
plt.bar(xvalues + widths[5], heights_cuquantum["import_time"],
color=greys[1], align="center", width=width, alpha=1, hatch=hatches[1],
edgecolor='w')
plt.bar(xvalues + widths[0], heights_numba["dry_run_time"],
color=oranges[0], align="center", width=width, alpha=1, hatch=hatches[0],
edgecolor='w', bottom=heights_numba["import_time"] + heights_numba["creation_time"])
plt.bar(xvalues + widths[1], heights_numba["simulation_times_mean"],
color=oranges[1], align="center", width=width, alpha=1, hatch=hatches[1],
edgecolor='w', bottom=heights_numba["import_time"] + heights_numba["creation_time"])
plt.bar(xvalues + widths[2], heights_cupy["dry_run_time"],
color=purples[0], align="center", width=width, alpha=1, hatch=hatches[0],
edgecolor='w', bottom=heights_cupy["import_time"] + heights_cupy["creation_time"])
plt.bar(xvalues + widths[3], heights_cupy["simulation_times_mean"],
color=purples[1], align="center", width=width, alpha=1, hatch=hatches[1],
edgecolor='w', bottom=heights_cupy["import_time"] + heights_cupy["creation_time"])
plt.bar(xvalues + widths[4], heights_cuquantum["dry_run_time"],
color=greens[0], align="center", width=width, alpha=1, hatch=hatches[0],
edgecolor='w', bottom=heights_cuquantum["import_time"] + heights_cuquantum["creation_time"])
plt.bar(xvalues + widths[5], heights_cuquantum["simulation_times_mean"],
color=greens[1], align="center", width=width, alpha=1, hatch=hatches[1],
edgecolor='w', bottom=heights_cuquantum["import_time"] + heights_cuquantum["creation_time"])
plt.xlabel("Number of qubits")
plt.ylabel("Execution time (sec)")
legend_elements = [
Patch(facecolor="w", edgecolor="k", hatch=hatches[0], label="Dry run time"),
Patch(facecolor="w", edgecolor="k", hatch=hatches[1], label="Simulation time"),
Patch(color=greys[1], label="Import time"),
Patch(color=oranges[1], label="numba"),
Patch(color=purples[1], label="cupy"),
Patch(color=greens[1], label="cuquantum"),
]
plt.legend(handles=legend_elements)
if save:
plt.savefig(f"qibojit_dry_vs_simulation_{circuit}_{precision}.pdf", bbox_inches="tight")
else:
plt.show()
def plot_breakdown_circuits(data, nqubits, precision="double", width=0.1, fontsize=30, save=False):
"""Creates dry run vs simulation barplot with import time breakdown for given number of qubits varying the circuit."""
matplotlib.rcParams["font.size"] = fontsize
# Set plot params
hatches = ['/', '\\', 'o', '-', 'x', '.', '*']
width = 0.1
quantities = ["import_time", "creation_time", "dry_run_time", "simulation_times_mean"]
circuits = ["qft", "variational", "supremacy", "qv", "bv"]
greys = sns.color_palette("Greys", 2)
purples = sns.color_palette("Purples", 2)
greens = sns.color_palette("Greens", 2)
plt.figure(figsize=(25, 9))
plt.title(f"qibojit - Dry run vs simulation - {nqubits} qubits")
xvalues = np.array(range(len(circuits)))
plt.xticks(xvalues, circuits)
base_condition = ((data["precision"] == precision) & (data["nqubits"] == nqubits))
condition = base_condition & (data["library_options"] == "backend=qibojit,platform=cupy")
heights_cupy = {q: np.array([float(data[condition & (data["circuit"] == circ)][q]) for circ in circuits])
for q in quantities}
condition = base_condition & (data["library_options"] == "backend=qibojit,platform=cuquantum")
heights_cuquantum = {q: np.array([float(data[condition & (data["circuit"] == circ)][q]) for circ in circuits])
for q in quantities}
plt.bar(xvalues - 3 * width / 2, heights_cupy["import_time"],
color=greys[0], align="center", width=width, alpha=1, hatch=hatches[0],
edgecolor='w')
plt.bar(xvalues - width / 2, heights_cupy["import_time"],
color=greys[1], align="center", width=width, alpha=1, hatch=hatches[1],
edgecolor='w')
plt.bar(xvalues + width / 2, heights_cuquantum["import_time"],
color=greys[0], align="center", width=width, alpha=1, hatch=hatches[0],
edgecolor='w')
plt.bar(xvalues + 3 * width / 2, heights_cuquantum["import_time"],
color=greys[1], align="center", width=width, alpha=1, hatch=hatches[1],
edgecolor='w')
plt.bar(xvalues - 3 * width / 2, heights_cupy["dry_run_time"],
color=purples[0], align="center", width=width, alpha=1, hatch=hatches[0],
edgecolor='w', bottom=heights_cupy["import_time"] + heights_cupy["creation_time"])
plt.bar(xvalues - width / 2, heights_cupy["simulation_times_mean"],
color=purples[1], align="center", width=width, alpha=1, hatch=hatches[1],
edgecolor='w', bottom=heights_cupy["import_time"] + heights_cupy["creation_time"])
plt.bar(xvalues + width / 2, heights_cuquantum["dry_run_time"],
color=greens[0], align="center", width=width, alpha=1, hatch=hatches[0],
edgecolor='w', bottom=heights_cuquantum["import_time"] + heights_cuquantum["creation_time"])
plt.bar(xvalues + 3 * width / 2, heights_cuquantum["simulation_times_mean"],
color=greens[1], align="center", width=width, alpha=1, hatch=hatches[1],
edgecolor='w', bottom=heights_cuquantum["import_time"] + heights_cuquantum["creation_time"])
plt.ylabel("Execution time (sec)")
legend_elements = [
Patch(facecolor="w", edgecolor="k", hatch=hatches[0], label="Dry run time"),
Patch(facecolor="w", edgecolor="k", hatch=hatches[1], label="Simulation time"),
Patch(color=greys[1], label="Import time"),
Patch(color=purples[1], label="cupy"),
Patch(color=greens[1], label="cuquantum"),
]
plt.legend(handles=legend_elements, bbox_to_anchor=(1,1))
if save:
plt.savefig(f"qibojit_dry_vs_simulation_{nqubits}qubits_{precision}.pdf", bbox_inches="tight")
else:
plt.show()
def plot_multigpu(data, nqubits, quantity, precision="double", fontsize=45, legend=False, save=False):
matplotlib.rcParams["font.size"] = fontsize
# Set plot params
hatches = ['/', '\\', 'o', '-', 'x', '.', '*']
width = 0.1
quantities = ["import_time", "creation_time", "dry_run_time", "simulation_times_mean",
"total_simulation_time", "total_dry_time"]
circuits = ["qft", "variational", "supremacy", "qv", "bv"]
widths = [-5 * width / 2, - 3 * width / 2, -width / 2, width / 2, 3 * width / 2, 5 * width / 2]
oranges = sns.color_palette("Oranges", 3)
purples = sns.color_palette("Purples", 3)
greens = sns.color_palette("Greens", 3)
# Plot the results
plt.figure(figsize=(25, 9))
xvalues = np.array(range(len(circuits)))
plt.xticks(xvalues, circuits)
base_condition = ((data["precision"] == precision) & (data["nqubits"] == nqubits))
heights1 = {}
heights2 = {}
heights4 = {}
for backend in ["qibojit", "qibotf"]:
condition = base_condition & (data["library_options"] == f"backend={backend},accelerators=4/GPU:3")
heights1[backend] = {q: np.array([float(data[condition & (data["circuit"] == c)][q]) for c in circuits])
for q in quantities}
condition = base_condition & (data["library_options"] == f"backend={backend},accelerators=2/GPU:2+2/GPU:3")
heights2[backend] = {q: np.array([float(data[condition & (data["circuit"] == c)][q]) for c in circuits])
for q in quantities}
condition = base_condition & (data["library_options"] == f"backend={backend},accelerators=1/GPU:0+1/GPU:1+1/GPU:2+1/GPU:3")
heights4[backend] = {q: np.array([float(data[condition & (data["circuit"] == c)][q]) for c in circuits])
for q in quantities}
plt.bar(xvalues + widths[0], heights1["qibojit"][quantity],
color=purples[0], align="center", width=width, alpha=1, hatch=hatches[0], edgecolor='w')
plt.bar(xvalues + widths[1], heights1["qibotf"][quantity],
color=greens[0], align="center", width=width, alpha=1, hatch=hatches[1], edgecolor='w')
plt.bar(xvalues + widths[2], heights2["qibojit"][quantity],
color=purples[1], align="center", width=width, alpha=1, hatch=hatches[0], edgecolor='w')
plt.bar(xvalues + widths[3], heights2["qibotf"][quantity],
color=greens[1], align="center", width=width, alpha=1, hatch=hatches[1], edgecolor='w')
plt.bar(xvalues + widths[4], heights4["qibojit"][quantity],
color=purples[2], align="center", width=width, alpha=1, hatch=hatches[0], edgecolor='w')
plt.bar(xvalues + widths[5], heights4["qibotf"][quantity],
color=greens[2], align="center", width=width, alpha=1, hatch=hatches[1], edgecolor='w')
plt.title(f"Multi-GPU - {nqubits} qubits")
if quantity == "total_dry_time":
plt.ylabel("Total dry run time (sec)")
elif quantity == "dry_run_time":
plt.ylabel("Dry run time (sec)")
elif quantity == "total_simulation_time":
plt.ylabel("Total simulation time (sec)")
elif quantity == "simulation_times_mean":
plt.ylabel("Simulation time (sec)")
legend_elements = [
Patch(facecolor=purples[2], edgecolor="w", hatch=hatches[0], label="qibojit"),
Patch(facecolor=greens[2], edgecolor="w", hatch=hatches[1], label="qibotf"),
Patch(color=purples[0], label="1x GPU"),
Patch(color=purples[1], label="2x GPUs"),
Patch(color=purples[2], label="4x GPUs"),
]
if legend:
plt.legend(handles=legend_elements, bbox_to_anchor=(1,1))
if save:
plt.savefig(f"multigpu_{nqubits}qubits_{quantity}_{precision}.pdf", bbox_inches="tight")
else:
plt.show()

View File

@@ -0,0 +1,44 @@
"""Scaling plots with performance comparison of qibojit backend run on different CPU and GPU devices."""
import matplotlib
import matplotlib.pyplot as plt
import seaborn as sns
matplotlib.rcParams['mathtext.fontset'] = 'cm'
matplotlib.rcParams['font.family'] = 'STIXGeneral'
class Line:
def __init__(self, label, data, color, marker, linestyle="-"):
self.label = label
self.data = data
self.color = color
self.marker = marker
self.linestyle = linestyle
def plot_devices(lines, circuit, quantity, precision="double",
fontsize=30, legendfont=None, save=False):
matplotlib.rcParams["font.size"] = fontsize
# Filter data
for line in lines:
condition = (line.data["circuit"] == circuit) & (line.data["precision"] == precision)
line.data = line.data[condition]
plt.figure(figsize=(14, 8))
for line in lines:
plt.semilogy(line.data["nqubits"], line.data[quantity], color=line.color, linestyle=line.linestyle,
linewidth=3.0, marker=line.marker, markersize=10, label=line.label)
plt.title(f"qibojit, {circuit}, {precision} precision")
plt.xlabel("Number of qubits")
if quantity == "total_dry_time":
plt.ylabel("Total dry run time (sec)")
elif quantity == "total_simulation_time":
plt.ylabel("Total simulation time (sec)")
if legendfont is not None:
plt.legend(loc="upper left", fontsize=legendfont)
if save:
plt.savefig(f"devices_{circuit}_{quantity}_{precision}.pdf", bbox_inches="tight")
else:
plt.show()

View File

@@ -0,0 +1,101 @@
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import seaborn as sns
from matplotlib.patches import Patch
matplotlib.rcParams['mathtext.fontset'] = 'cm'
matplotlib.rcParams['font.family'] = 'STIXGeneral'
def plot_dense(data, quantity, nqubits, fontsize=30, legend=True, save=False):
matplotlib.rcParams["font.size"] = fontsize
cpu_cp = sns.color_palette("Oranges", 4)
gpu_cp = sns.color_palette("Purples", 4)
data["is_gpu"] = data["device"].apply(lambda x: "GPU" in x)
base_condition = (data["nqubits"] == nqubits) & (data["dense"] == True)
plt.figure(figsize=(16, 9))
condition = base_condition & (data["backend"] == "numpy")
plt.semilogy(data[condition]["dt"], data[condition][quantity], marker="^", markersize=10,
color=cpu_cp[3], linewidth=3.0, label="numpy")
condition = base_condition & (data["backend"] == "tensorflow") & (data["is_gpu"] == False)
plt.semilogy(data[condition]["dt"], data[condition][quantity], marker="o", markersize=10,
color=cpu_cp[1], linewidth=3.0, label="tensorflow cpu")
condition = base_condition & (data["backend"] == "qibojit") & (data["platform"] == "cuquantum")
plt.semilogy(data[condition]["dt"], data[condition][quantity], marker="^", markersize=10,
color=gpu_cp[3], linewidth=3.0, label="cupy")
condition = base_condition & (data["backend"] == "tensorflow") & (data["is_gpu"] == True)
plt.semilogy(data[condition]["dt"], data[condition][quantity], marker="o", markersize=10,
color=gpu_cp[1], linewidth=3.0, label="tensorflow gpu")
plt.title(f"Dense adiabatic evolution, {nqubits} qubits, double precision")
plt.xlabel("$\delta t$")
if quantity == "total_dry_time":
plt.ylabel("Total dry run time (sec)")
elif quantity == "total_simulation_time":
plt.ylabel("Total simulation time (sec)")
if legend:
plt.legend()
if save:
plt.savefig(f"evolution_dense_{nqubits}qubits_{quantity}.pdf", bbox_inches="tight")
else:
plt.show()
def plot_trotter(data, quantity, nqubits, fontsize=30, yticks=None, legend=False, save=False):
matplotlib.rcParams["font.size"] = fontsize
cpu_cp = sns.color_palette("Oranges", 4)
gpu_cp = sns.color_palette("Purples", 4)
data["is_gpu"] = data["device"].apply(lambda x: "GPU" in x)
base_condition = (data["nqubits"] == nqubits) & (data["dense"] == False)
plt.figure(figsize=(16, 9))
condition = base_condition & (data["backend"] == "numpy")
plt.semilogy(data[condition]["dt"], data[condition][quantity], marker="s", markersize=10,
color=cpu_cp[0], linewidth=3.0, label="numpy")
condition = base_condition & (data["backend"] == "tensorflow") & (data["is_gpu"] == False)
plt.semilogy(data[condition]["dt"], data[condition][quantity], marker="o", markersize=10,
color=cpu_cp[1], linewidth=3.0, label="tensorflow cpu")
condition = base_condition & (data["backend"] == "qibotf") & (data["is_gpu"] == False)
plt.semilogy(data[condition]["dt"], data[condition][quantity], marker="D", markersize=10,
color=cpu_cp[2], linewidth=3.0, label="qibotf cpu")
condition = base_condition & (data["backend"] == "qibojit") & (data["platform"] == "numba")
plt.semilogy(data[condition]["dt"], data[condition][quantity], marker="^", markersize=10,
color=cpu_cp[3], linewidth=3.0, label="qibojit (numba) cpu")
condition = base_condition & (data["backend"] == "tensorflow") & (data["is_gpu"] == True)
plt.semilogy(data[condition]["dt"], data[condition][quantity], marker="o", markersize=10,
color=gpu_cp[1], linewidth=3.0, label="tensorflow gpu")
condition = base_condition & (data["backend"] == "qibotf") & (data["is_gpu"] == True)
plt.semilogy(data[condition]["dt"], data[condition][quantity], marker="D", markersize=10,
color=gpu_cp[2], linewidth=3.0, label="qibotf gpu")
condition = base_condition & (data["backend"] == "qibojit") & (data["platform"] == "cupy")
plt.semilogy(data[condition]["dt"], data[condition][quantity], marker="^", markersize=10,
color=gpu_cp[3], linewidth=3.0, label="qibojit (cupy) gpu")
condition = base_condition & (data["backend"] == "qibojit") & (data["platform"] == "cuquantum")
plt.semilogy(data[condition]["dt"], data[condition][quantity], marker="v", markersize=10, linestyle="--",
color=gpu_cp[3], linewidth=3.0, label="qibojit (cuquantum) gpu")
plt.title(f"Trotter adiabatic evolution, {nqubits} qubits, double precision")
plt.xlabel("$\delta t$")
if quantity == "total_dry_time":
plt.ylabel("Total dry run time (sec)")
elif quantity == "total_simulation_time":
plt.ylabel("Total simulation time (sec)")
if legend:
plt.legend(fontsize="small")
if yticks is not None:
plt.minorticks_off()
plt.yticks(yticks)
if save:
plt.savefig(f"evolution_trotter_{nqubits}qubits_{quantity}.pdf", bbox_inches="tight")
else:
plt.show()

View File

@@ -0,0 +1,145 @@
"""Generates bar plots for gate fusion comparisons."""
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import seaborn as sns
from matplotlib.patches import Patch
matplotlib.rcParams['mathtext.fontset'] = 'cm'
matplotlib.rcParams['font.family'] = 'STIXGeneral'
def plot_fusion_nqubits(data, circuit, quantity, precision="double", width=0.1, fontsize=30, legend=False, logscale=False, save=False):
matplotlib.rcParams["font.size"] = fontsize
# Set plot params
hatches = ['/', '\\', 'o', '-', 'x', '.', '*']
nqubits = [20, 22, 24, 26, 28]
widths = [-5 * width / 2, - 3 * width / 2, -width / 2, width / 2, 3 * width / 2, 5 * width / 2]
oranges = sns.color_palette("Oranges", 2)
purples = sns.color_palette("Purples", 2)
greens = sns.color_palette("Greens", 2)
# Plot the results
plt.figure(figsize=(25, 9))
plt.title(f"qibojit - Gate fusion - {circuit}")
xvalues = np.array(range(len(nqubits)))
plt.xticks(xvalues, nqubits)
base_condition = ((data["precision"] == precision) & (data["circuit"] == circuit))
condition = base_condition & (data["library_options"] == "backend=qibojit,platform=numba")
heights = np.array([float(data[condition & (data["nqubits"] == n)][quantity]) for n in nqubits])
plt.bar(xvalues + widths[0], heights, color=oranges[0], align="center", width=width,
log=logscale, alpha=1, hatch=hatches[0], edgecolor='w')
condition = base_condition & (data["library_options"] == "backend=qibojit,platform=numba,max_qubits=2")
heights = np.array([float(data[condition & (data["nqubits"] == n)][quantity]) for n in nqubits])
plt.bar(xvalues + widths[1], heights, color=oranges[1], align="center", width=width,
log=logscale, alpha=1, hatch=hatches[1], edgecolor='w')
condition = base_condition & (data["library_options"] == "backend=qibojit,platform=cupy")
heights = np.array([float(data[condition & (data["nqubits"] == n)][quantity]) for n in nqubits])
plt.bar(xvalues + widths[2], heights, color=purples[0], align="center", width=width,
log=logscale, alpha=1, hatch=hatches[0], edgecolor='w')
condition = base_condition & (data["library_options"] == "backend=qibojit,platform=cupy,max_qubits=2")
heights = np.array([float(data[condition & (data["nqubits"] == n)][quantity]) for n in nqubits])
plt.bar(xvalues + widths[3], heights, color=purples[1], align="center", width=width,
log=logscale, alpha=1, hatch=hatches[1], edgecolor='w')
condition = base_condition & (data["library_options"] == "backend=qibojit,platform=cuquantum")
heights = np.array([float(data[condition & (data["nqubits"] == n)][quantity]) for n in nqubits])
plt.bar(xvalues + widths[4], heights, color=greens[0], align="center", width=width,
log=logscale, alpha=1, hatch=hatches[0], edgecolor='w')
condition = base_condition & (data["library_options"] == "backend=qibojit,platform=cuquantum,max_qubits=2")
heights = np.array([float(data[condition & (data["nqubits"] == n)][quantity]) for n in nqubits])
plt.bar(xvalues + widths[5], heights, color=greens[1], align="center", width=width,
log=logscale, alpha=1, hatch=hatches[1], edgecolor='w')
plt.xlabel("Number of qubits")
if quantity == "total_dry_time":
plt.ylabel("Total dry run time (sec)")
elif quantity == "total_simulation_time":
plt.ylabel("Total simulation time (sec)")
if legend:
legend_elements = [
Patch(facecolor="w", edgecolor="k", hatch=hatches[0], label="No fusion"),
Patch(facecolor="w", edgecolor="k", hatch=hatches[1], label="Two-qubit fusion"),
Patch(color=oranges[1], label="numba"),
Patch(color=purples[1], label="cupy"),
Patch(color=greens[1], label="cuquantum")
]
plt.legend(handles=legend_elements)
if save:
plt.savefig(f"qibojit_fusion_{precision}_{circuit}_{quantity}.pdf", bbox_inches="tight")
else:
plt.show()
def plot_fusion_circuits(data, nqubits, quantity, precision="double", width=0.1, fontsize=30, legend=False, logscale=False, save=False):
matplotlib.rcParams["font.size"] = fontsize
# Set plot params
hatches = ['/', '\\', 'o', '-', 'x', '.', '*']
circuits = ["qft", "variational", "supremacy", "qv", "bv"]
widths = [-5 * width / 2, - 3 * width / 2, -width / 2, width / 2, 3 * width / 2, 5 * width / 2]
oranges = sns.color_palette("Oranges", 2)
purples = sns.color_palette("Purples", 2)
greens = sns.color_palette("Greens", 2)
# Plot the results
plt.figure(figsize=(25, 9))
plt.title(f"qibojit - Gate fusion - {nqubits} qubits")
xvalues = np.array(range(len(circuits)))
plt.xticks(xvalues, circuits)
base_condition = ((data["precision"] == precision) & (data["nqubits"] == nqubits))
condition = base_condition & (data["library_options"] == "backend=qibojit,platform=numba")
heights = np.array([float(data[condition & (data["circuit"] == c)][quantity]) for c in circuits])
plt.bar(xvalues + widths[0], heights, color=oranges[0], align="center", width=width,
log=logscale, alpha=1, hatch=hatches[0], edgecolor='w')
condition = base_condition & (data["library_options"] == "backend=qibojit,platform=numba,max_qubits=2")
heights = np.array([float(data[condition & (data["circuit"] == c)][quantity]) for c in circuits])
plt.bar(xvalues + widths[1], heights, color=oranges[1], align="center", width=width,
log=logscale, alpha=1, hatch=hatches[1], edgecolor='w')
condition = base_condition & (data["library_options"] == "backend=qibojit,platform=cupy")
heights = np.array([float(data[condition & (data["circuit"] == c)][quantity]) for c in circuits])
plt.bar(xvalues + widths[2], heights, color=purples[0], align="center", width=width,
log=logscale, alpha=1, hatch=hatches[0], edgecolor='w')
condition = base_condition & (data["library_options"] == "backend=qibojit,platform=cupy,max_qubits=2")
heights = np.array([float(data[condition & (data["circuit"] == c)][quantity]) for c in circuits])
plt.bar(xvalues + widths[3], heights, color=purples[1], align="center", width=width,
log=logscale, alpha=1, hatch=hatches[1], edgecolor='w')
condition = base_condition & (data["library_options"] == "backend=qibojit,platform=cuquantum")
heights = np.array([float(data[condition & (data["circuit"] == c)][quantity]) for c in circuits])
plt.bar(xvalues + widths[4], heights, color=greens[0], align="center", width=width,
log=logscale, alpha=1, hatch=hatches[0], edgecolor='w')
condition = base_condition & (data["library_options"] == "backend=qibojit,platform=cuquantum,max_qubits=2")
heights = np.array([float(data[condition & (data["circuit"] == c)][quantity]) for c in circuits])
plt.bar(xvalues + widths[5], heights, color=greens[1], align="center", width=width,
log=logscale, alpha=1, hatch=hatches[1], edgecolor='w')
if quantity == "total_dry_time":
plt.ylabel("Total dry run time (sec)")
elif quantity == "total_simulation_time":
plt.ylabel("Total simulation time (sec)")
if legend:
legend_elements = [
Patch(facecolor="w", edgecolor="k", hatch=hatches[0], label="No fusion"),
Patch(facecolor="w", edgecolor="k", hatch=hatches[1], label="Two-qubit fusion"),
Patch(color=oranges[1], label="numba"),
Patch(color=purples[1], label="cupy"),
Patch(color=greens[1], label="cuquantum")
]
plt.legend(handles=legend_elements, bbox_to_anchor=(1,1))
if save:
plt.savefig(f"qibojit_fusion_{precision}_{nqubits}qubits_{quantity}.pdf", bbox_inches="tight")
else:
plt.show()

View File

@@ -0,0 +1,73 @@
import numpy as np
import pandas as pd
import matplotlib
import matplotlib.pyplot as plt
import seaborn as sns
from matplotlib.patches import Patch
matplotlib.rcParams['mathtext.fontset'] = 'cm'
matplotlib.rcParams['font.family'] = 'STIXGeneral'
class Library:
"""Defines color, hatch and label for each library."""
def __init__(self, name, color, hatch, label, has_double=True, has_single=True, alpha=None):
self.name = name
self.color = color
self.hatch = hatch
self.label = label
self.has_double = has_double
self.has_single = has_single
if alpha is None:
self.alpha = 1.0 if "GPU" in self.name else 0.5
else:
self.alpha = alpha
def has(self, precision):
return getattr(self, f"has_{precision}")
def plot_libraries(libraries, cpu_data, gpu_data, quantity, nqubits,
precision="double", width=0.07, fontsize=45,
legend=False, logscale=True, fusion=False, save=False):
matplotlib.rcParams["font.size"] = fontsize
# Process data
gpu_data = gpu_data.copy()
gpu_data["library"] += " GPU"
data = pd.concat([cpu_data, gpu_data])
circuits = ["qft", "variational", "supremacy", "qv", "bv"]
# create widths list for bar positioning
n = len([library for library in libraries if library.has(precision)])
ws = np.arange(n)
ws = iter((ws - ws[n // 2]) * width)
# Plot the results
xvalues = np.array(range(len(circuits)))
plt.figure(figsize=(25, 9))
base_condition = (data["nqubits"] == nqubits) & (data["precision"] == precision)
for library in libraries:
if library.has(precision):
condition = base_condition & (data["library"] == library.name)
height = np.array([float(data[condition & (data["circuit"] == c)][quantity]) for c in circuits])
plt.bar(xvalues + next(ws), height, color=library.color, align="center",
width=width, alpha=library.alpha, label=library.label,
log=logscale, edgecolor='w', hatch=library.hatch)
if fusion:
plt.title(f"{nqubits} qubits - Two-qubit fusion - {precision} precision")
else:
plt.title(f"{nqubits} qubits - {precision} precision")
if quantity == "total_dry_time":
plt.ylabel("Total dry time (sec)")
elif quantity == "total_simulation_time":
plt.ylabel("Total simulation time (sec)")
plt.xticks(xvalues, circuits)
if legend:
plt.legend(fontsize="small", bbox_to_anchor=(1,1))
if save:
savename = "libraries_fusion" if fusion else "libraries"
plt.savefig(f"{savename}_{precision}_{nqubits}qubits_{quantity}.pdf", bbox_inches="tight")
else:
plt.show()

View File

@@ -0,0 +1,337 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "76badf4a",
"metadata": {},
"source": [
"This notebook shows how to generate the benchmark plots used in the paper. \n",
"\n",
"To generate the plots using the benchmarks of the original paper, download the following gist:\n",
"\n",
"[stavros11/ffb88a5b914b60213515f0256c0e8aa4](https://gist.github.com/stavros11/ffb88a5b914b60213515f0256c0e8aa4)\n",
"\n",
"copy the contents in a folder named `/data` in the directory of this notebook and execute all cells.\n",
"\n",
"The logs provided in the gist serve as a template.\n",
"The same plotting functionality should work with logs generated from different machines.\n",
"To generate new logs from scratch one can use the bash scripts provided in the `scripts/` directory."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "97f43ed0",
"metadata": {},
"outputs": [],
"source": [
"from utils import load_data, load_evolution_data\n",
"\n",
"save = False # if ``True`` plots will be saved in the current directory as pdfs"
]
},
{
"cell_type": "markdown",
"id": "f4d6d97f",
"metadata": {},
"source": [
"## Figure 3\n",
"\n",
"Bar plot with import breakdown and dry run vs simulation comparison for qibojit."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ba717379",
"metadata": {
"scrolled": false
},
"outputs": [],
"source": [
"from barplots import plot_breakdown_nqubits\n",
"\n",
"data = load_data(f\"./data/qibojit_breakdown.dat\")\n",
"plot_breakdown_nqubits(data, \"supremacy\", save=save)"
]
},
{
"cell_type": "markdown",
"id": "6e2eeb0b",
"metadata": {},
"source": [
"## Figure 4\n",
"\n",
"Scaling plots of execution time as a function of the number of qubits for all qibo backends."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1ba0a87d",
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"from scaling import plot_scaling\n",
"\n",
"cpu_data = load_data(\"./data/qibo_scaling_cpu.dat\")\n",
"gpu_data = load_data(\"./data/qibo_scaling_gpu.dat\")\n",
"\n",
"plot_scaling(cpu_data, gpu_data, \"qft\", \"total_dry_time\", legend=False, save=save)\n",
"plot_scaling(cpu_data, gpu_data, \"qft\", \"total_simulation_time\", save=save)"
]
},
{
"cell_type": "markdown",
"id": "8cb5555a",
"metadata": {},
"source": [
"## Figure 5\n",
"\n",
"qibojit backend performance on different CPU and GPU devices."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "895cb582",
"metadata": {
"scrolled": false
},
"outputs": [],
"source": [
"import seaborn as sns # used for color palettes\n",
"from devices import Line, plot_devices\n",
"\n",
"oranges = sns.color_palette(\"Oranges\", 2)\n",
"greens = sns.color_palette(\"Greens\", 2)\n",
"blues = sns.color_palette(\"Blues\", 3)\n",
"\n",
"lines = [\n",
" Line(\"NVIDIA RTX A6000 (cupy)\", load_data(\"./data/qibo_scaling_gpu.dat\", qibojit_only=True), blues[2], \"o\"),\n",
" Line(\"NVIDIA DGX V100 (cupy)\", load_data(\"./data/dgx_qibojit.dat\", qibojit_only=True), blues[1], \"^\"),\n",
" Line(\"NVIDIA GTX 1650 (cupy)\", load_data(\"./data/gtx1650_qibojit.dat\", qibojit_only=True), blues[0], \"d\"),\n",
" Line(\"AMD Radeon VII (cupy)\", load_data(\"./data/rocm_qibojit.dat\"), greens[1], \"v\"),\n",
" Line(\"NVIDIA RTX A6000 (cupy-multigpu)\", load_data(\"./data/rtx_multigpu.dat\", qibojit_only=True), blues[2], \"o\", linestyle=\"--\"),\n",
" Line(\"AMD EPYC 7742, 128 th., 2TB (numba)\", load_data(\"./data/qibo_scaling_cpu.dat\", qibojit_only=True), oranges[1], \"\"),\n",
" Line(\"ATOS QLM, 384 th., 6TB (numba)\", load_data(\"./data/qlm_qibojit.dat\", qibojit_only=True), oranges[0], \"\"),\n",
"]\n",
"# filter qibojit-cupy only data if the log file contains more (eg. qibojit-cuquantum)\n",
"is_cupy = lines[0].data[\"library_options\"].apply(lambda x: \"cupy\" in x)\n",
"lines[0].data = lines[0].data[is_cupy == True]\n",
"\n",
"plot_devices(lines, \"qft\", \"total_dry_time\", save=save)\n",
"plot_devices(lines, \"qft\", \"total_simulation_time\", legendfont=26, save=save)"
]
},
{
"cell_type": "markdown",
"id": "5cd4c946",
"metadata": {},
"source": [
"## Figure 6\n",
"\n",
"Bar plot with different multigpu configurations and qibojit vs qibotf comparison."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "15099a54",
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"from barplots import plot_multigpu\n",
"\n",
"data = load_data(\"./data/dgx_multigpu.dat\")\n",
"plot_multigpu(data, 32, \"total_dry_time\", save=save)\n",
"plot_multigpu(data, 32, \"total_simulation_time\", legend=True, save=save)"
]
},
{
"cell_type": "markdown",
"id": "64538a61",
"metadata": {},
"source": [
"## Figure 7\n",
"\n",
"Bar plot with comparisons between different simulation libraries on various circuits."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "81035c0e",
"metadata": {
"scrolled": false
},
"outputs": [],
"source": [
"import seaborn as sns\n",
"from libraries import Library, plot_libraries\n",
"\n",
"cpu_data = load_data(\"./data/libraries_cpu.dat\")\n",
"gpu_data = load_data(\"./data/libraries_gpu.dat\")\n",
"\n",
"palette = sns.color_palette(\"bright\", 7)\n",
"libraries = [\n",
" Library(\"qibo\", palette[0], \"/\", \"Qibo\"),\n",
" Library(\"qibo GPU\", palette[0], \"/\", \"Qibo GPU\"),\n",
" Library(\"qiskit\", palette[1], \"-\", \"Qiskit\"),\n",
" Library(\"qiskit-gpu GPU\", palette[1], \"-\", \"Qiskit GPU\"),\n",
" Library(\"hybridq\", palette[2], \"x\", \"HybridQ\"),\n",
" Library(\"hybridq-gpu GPU\", palette[2], \"x\", \"HybridQ GPU\"),\n",
" Library(\"qulacs\", palette[4], \"\\\\\", \"Qulacs\", has_single=False),\n",
" Library(\"qulacs-gpu GPU\", palette[4], \"\\\\\", \"Qulacs GPU\", has_single=False),\n",
" Library(\"projectq\", palette[3], \"o\", \"ProjectQ\", has_single=False),\n",
" Library(\"qcgpu GPU\", palette[3], \"o\", \"QCGPU\", has_double=False)\n",
"]\n",
"\n",
"plot_libraries(libraries, cpu_data, gpu_data, \"total_dry_time\", 20, precision=\"single\", legend=False, save=save)\n",
"plot_libraries(libraries, cpu_data, gpu_data, \"total_dry_time\", 30, precision=\"single\", legend=True, save=save)\n",
"\n",
"plot_libraries(libraries, cpu_data, gpu_data, \"total_dry_time\", 20, precision=\"double\", legend=False, save=save)\n",
"plot_libraries(libraries, cpu_data, gpu_data, \"total_dry_time\", 30, precision=\"double\", legend=True, save=save)"
]
},
{
"cell_type": "markdown",
"id": "20eb1827",
"metadata": {},
"source": [
"## Figure 8\n",
"\n",
"Bar plot comparing fusion vs no fusion for all qibojit platforms and circuits"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e0a127b8",
"metadata": {
"scrolled": false
},
"outputs": [],
"source": [
"from fusion import plot_fusion_circuits\n",
"\n",
"data = load_data(f\"./data/qibojit_fusion.dat\")\n",
"plot_fusion_circuits(data, 30, \"total_dry_time\", fontsize=38, legend=True, save=True)\n",
"plot_fusion_circuits(data, 30, \"total_simulation_time\", fontsize=38, legend=True, save=save)"
]
},
{
"cell_type": "markdown",
"id": "909fbaeb",
"metadata": {},
"source": [
"## Figure 9\n",
"\n",
"Bar plot comparing two-qubit fusion for different libraries (qibo, qiskit, qsim)."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "60e32824",
"metadata": {},
"outputs": [],
"source": [
"import seaborn as sns\n",
"from libraries import Library, plot_libraries\n",
"\n",
"cpu_data = load_data(\"./data/libraries_fusion_cpu.dat\")\n",
"gpu_data = load_data(\"./data/libraries_fusion_gpu.dat\")\n",
"\n",
"palette = sns.color_palette(\"bright\", 7)\n",
"libraries = [\n",
" Library(\"qibo\", palette[0], \"/\", \"Qibo (numba)\", alpha=0.3),\n",
" Library(\"qibo GPU\", palette[0], \"/\", \"Qibo (cupy) GPU\", alpha=1.0),\n",
" Library(\"qibo-cuquantum GPU\", palette[0], \"/\", \"Qibo (cuquantum) GPU\", alpha=0.6),\n",
" Library(\"qiskit\", palette[1], \"-\", \"Qiskit\", alpha=0.3),\n",
" Library(\"qiskit-gpu GPU\", palette[1], \"-\", \"Qiskit GPU\", alpha=1.0),\n",
" Library(\"qsim\", palette[2], \"\\\\\", \"qsim\", has_double=False, alpha=0.3),\n",
" Library(\"qsim-gpu GPU\", palette[2], \"\\\\\", \"qsim GPU\", has_double=False, alpha=1.0),\n",
" Library(\"qsim-cuquantum GPU\", palette[2], \"\\\\\", \"qsim (cuquantum) GPU\", has_double=False, alpha=0.6),\n",
"]\n",
"\n",
"plot_libraries(libraries, cpu_data, gpu_data, \"total_dry_time\", 30, precision=\"single\", \n",
" legend=True, fontsize=45, logscale=True, fusion=True, save=save)"
]
},
{
"cell_type": "markdown",
"id": "a5392b2d",
"metadata": {},
"source": [
"## Figure 10\n",
"\n",
"Scaling plot vs time dt for adiabatic evolution of TFIM Hamiltonian using the dense form."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6d7c77f0",
"metadata": {},
"outputs": [],
"source": [
"from evolution import plot_dense\n",
"\n",
"data = load_evolution_data(\"data/evolution.dat\")\n",
"plot_dense(data, \"total_dry_time\", 10, save=save)"
]
},
{
"cell_type": "markdown",
"id": "0b8e88e7",
"metadata": {},
"source": [
"## Figure 11\n",
"\n",
"Scaling plot vs time dt for adiabatic evolution of TFIM Hamiltonian using the Trotter decomposition."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "67f4884c",
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"from evolution import plot_trotter\n",
"\n",
"data = load_evolution_data(\"data/evolution.dat\")\n",
"plot_trotter(data, \"total_dry_time\", 10, yticks=[1, 10], legend=True, save=save)\n",
"plot_trotter(data, \"total_dry_time\", 20, yticks=[1, 10, 100], legend=False, save=save)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.12"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@@ -0,0 +1,56 @@
"""Generates qubit scaling plots for different qibo backends."""
import matplotlib
import matplotlib.pyplot as plt
import seaborn as sns
from matplotlib.patches import Patch
matplotlib.rcParams['mathtext.fontset'] = 'cm'
matplotlib.rcParams['font.family'] = 'STIXGeneral'
def plot_scaling(cpu_data, gpu_data, circuit, quantity, precision="double", fontsize=30, legend=True, save=False):
matplotlib.rcParams["font.size"] = fontsize
# Prepare GPU data
condition = (gpu_data["circuit"] == circuit) & (gpu_data["precision"] == precision)
backends = ["tensorflow", "qibotf"]
data = {f"{k} GPU": gpu_data[(gpu_data["library_options"] == f"backend={k}") & condition] for k in backends}
data["qibojit cupy GPU"] = gpu_data[(gpu_data["library_options"] == "backend=qibojit,platform=cupy") & condition]
data["qibojit cuquantum GPU"] = gpu_data[(gpu_data["library_options"] == "backend=qibojit,platform=cuquantum") & condition]
# Prepare CPU data
backends = ["numpy", "tensorflow", "qibotf", "qibojit"]
condition = (cpu_data["circuit"] == circuit) & (cpu_data["precision"] == precision)
data.update({k: cpu_data[(cpu_data["library_options"] == f"backend={k}") & condition] for k in backends})
# Plot data
cpu_cp = sns.color_palette("Oranges", 4)
gpu_cp = sns.color_palette("Purples", 4)
plt.figure(figsize=(16, 9))
plt.semilogy(data["numpy"]["nqubits"], data["numpy"][quantity], marker="s", markersize=10,
color=cpu_cp[0], linewidth=3.0, label="numpy")
plt.semilogy(data["tensorflow"]["nqubits"], data["tensorflow"][quantity], marker="o", markersize=10,
color=cpu_cp[1], linewidth=3.0, label="tensorflow cpu")
plt.semilogy(data["qibotf"]["nqubits"], data["qibotf"][quantity], marker="D", markersize=10,
color=cpu_cp[2], linewidth=3.0, label="qibotf cpu")
plt.semilogy(data["qibojit"]["nqubits"], data["qibojit"][quantity],
color=cpu_cp[3], linewidth=3.0, label="qibojit (numba) cpu", marker="^", markersize=10)
plt.semilogy(data["tensorflow GPU"]["nqubits"], data["tensorflow GPU"][quantity], marker="o", markersize=10,
color=gpu_cp[1], linewidth=3.0, label="tensorflow gpu")
plt.semilogy(data["qibotf GPU"]["nqubits"], data["qibotf GPU"][quantity], marker="D", markersize=10,
color=gpu_cp[2], linewidth=3.0, label="qibotf gpu")
plt.semilogy(data["qibojit cupy GPU"]["nqubits"], data["qibojit cupy GPU"][quantity],
color=gpu_cp[3], linewidth=3.0, label="qibojit (cupy) gpu", marker="^", markersize=10)
plt.semilogy(data["qibojit cuquantum GPU"]["nqubits"], data["qibojit cuquantum GPU"][quantity],
color=gpu_cp[3], linewidth=3.0, linestyle="--", label="qibojit (cuquantum) gpu", marker="v", markersize=10)
plt.title(f"{circuit}, {precision} precision")
plt.xlabel("Number of qubits")
if quantity == "total_dry_time":
plt.ylabel("Total dry run time (sec)")
elif quantity == "total_simulation_time":
plt.ylabel("Total simulation time (sec)")
if legend:
plt.legend(fontsize="small")
if save:
plt.savefig(f"qibo_scaling_{circuit}_{quantity}_{precision}.pdf", bbox_inches="tight")
else:
plt.show()

View File

@@ -0,0 +1,36 @@
import json
import pandas as pd
def load_data(filename, qibojit_only=False):
with open(filename, "r") as file:
data = pd.DataFrame(json.load(file))
# filter data for qibojit
if qibojit_only:
is_qibojit = data["library_options"].apply(lambda x: "qibojit" in x)
data = data[is_qibojit]
data["total_dry_time"] = data["dry_run_time"] + data["creation_time"] + data["import_time"]
data["total_simulation_time"] = data["simulation_times_mean"] + data["creation_time"] + data["import_time"]
return data
def load_data_multigpu(filename, qibojit_only=False):
data = load_data(filename, qibojit_only)
data["backend"] = data["library_options"].apply(lambda x: x.split(",")[0].split("=")[-1])
data["accelerators"] = data["library_options"].apply(lambda x: x.split(",")[1].split("=")[-1])
data["nqubits (accelerators)"] = data.apply(lambda x: f"{x.nqubits} ({x.accelerators})", axis=1)
return data
def load_evolution_data(filename):
with open(filename, "r") as file:
data = pd.DataFrame(json.load(file))
data["creation_time"] = data["hamiltonian_creation_time"] + data["evolution_creation_time"]
data["total_dry_time"] = data["dry_run_time"] + data["creation_time"] + data["import_time"]
#if "simulation_times_mean" not in data.columns:
# data["simulation_times_mean"] = data["simulation_times"].apply(lambda x: np.mean(x))
data["total_simulation_time"] = data["simulation_times_mean"] + data["creation_time"] + data["import_time"]
return data