diff options
Diffstat (limited to 'archive/2024/winter/bsc_dichler/scripts/plot')
6 files changed, 593 insertions, 0 deletions
diff --git a/archive/2024/winter/bsc_dichler/scripts/plot/cas.py b/archive/2024/winter/bsc_dichler/scripts/plot/cas.py new file mode 100644 index 000000000..e6f3a08e1 --- /dev/null +++ b/archive/2024/winter/bsc_dichler/scripts/plot/cas.py @@ -0,0 +1,92 @@ +from pathlib import Path +import pandas as pd +import matplotlib.pyplot as plt +import numpy as np + + +def plot(output_root: Path, format): + output_root = output_root / Path("cas") + csv_file1 = output_root / Path("run.csv") + csv_file2 = output_root / Path("run_mte.csv") + + df1 = pd.read_csv(csv_file1, sep=";") + df2 = pd.read_csv(csv_file2, sep=";") + + df1["duration"] = df1["duration"] / 1_000_000_000 + df2["duration"] = df2["duration"] / 1_000_000_000 + + grouped1 = df1.groupby("cores")["duration"].agg(["mean", "std"]).reset_index() + grouped2 = df2.groupby("cores")["duration"].agg(["mean", "std"]).reset_index() + + merged = pd.merge(grouped1, grouped2, on="cores", suffixes=("_1", "_2")) + + _, ax1 = plt.subplots(figsize=(10, 6)) + + library = ["1 Thread", "2 Threads", "3 Threads", "4 Threads"] + x = np.arange(len(library)) + bar_width = 0.35 + + ax1.bar( + x - bar_width / 2, + merged["mean_1"], + yerr=merged["std_1"], + width=bar_width, + capsize=5, + label="MTE disabled", + color="#fc9272", + edgecolor="black", + linewidth=2, + ) + ax1.bar( + x + bar_width / 2, + merged["mean_2"], + yerr=merged["std_2"], + width=bar_width, + capsize=5, + label="MTE enabled", + color="#a6bddb", + edgecolor="black", + linewidth=2, + ) + + for i, row in merged.iterrows(): + x_start = i - 0.05 + + y_start = row["mean_2"] + y_end = row["mean_1"] + + if (y_start - row["std_2"]) <= (y_end + row["std_1"]): + continue + + ax1.annotate( + f"", + xy=(x_start - 0.25 / 2, y_start), + xytext=(x_start - 0.25 / 2, y_end + 0.05 * y_end), + arrowprops=dict(arrowstyle="->", color="red", lw=2), + color="red", + ha="center", + ) + + percentage = y_start / y_end + ax1.text( + x_start - 0.25 / 2, + y_start + ((y_end - y_start) / 2), + f"{percentage:.2f}×", + color="red", + fontweight="bold", + bbox=dict(facecolor="white", alpha=1.0, edgecolor="none"), + ha="center", + ) + + plt.xticks(x, library) + ax1.set_ylabel("Time (s)") + ax1.set_xlabel(r"#Threads") + + ax1.spines["top"].set_visible(False) + ax1.spines["right"].set_visible(False) + ax1.set_title("Lower is better ↓", color="navy") + ax1.legend(loc="upper left") + ax1.set_ylim(ymin=0) + + output = output_root / Path(f"result.{format}") + plt.savefig(output, format=format) diff --git a/archive/2024/winter/bsc_dichler/scripts/plot/contiguous.py b/archive/2024/winter/bsc_dichler/scripts/plot/contiguous.py new file mode 100644 index 000000000..24981138e --- /dev/null +++ b/archive/2024/winter/bsc_dichler/scripts/plot/contiguous.py @@ -0,0 +1,72 @@ +from pathlib import Path +import pandas as pd +import matplotlib.pyplot as plt + + +def plot(output_root: Path, format): + output_root = output_root / Path("contiguous") + csv_file1 = output_root / Path("load16.csv") + csv_file2 = output_root / Path("load16_mte.csv") + + df1 = pd.read_csv(csv_file1, sep=";") + df2 = pd.read_csv(csv_file2, sep=";") + + df1["kb"] = df1["len"] * 64 // 1024 + df2["kb"] = df2["len"] * 64 // 1024 + + grouped1 = df1.groupby("kb")["duration"].agg(["mean", "std"]).reset_index() + grouped2 = df2.groupby("kb")["duration"].agg(["mean", "std"]).reset_index() + + merged = pd.merge(grouped1, grouped2, on="kb", suffixes=("_1", "_2")) + + _, ax1 = plt.subplots(figsize=(10, 6)) + + ax1.errorbar( + merged["kb"], + merged["mean_1"], + yerr=merged["std_1"], + fmt="o-", + color="#a6bddb", + capsize=5, + label="MTE disabled", + ) + ax1.errorbar( + merged["kb"], + merged["mean_2"], + yerr=merged["std_2"], + fmt="s-", + color="#fc9272", + capsize=5, + label="MTE enabled", + ) + + merged["lower_1"] = merged["mean_1"] - merged["std_1"] + merged["lower_2"] = merged["mean_2"] - merged["std_2"] + merged["upper_1"] = merged["mean_1"] + merged["std_1"] + merged["upper_2"] = merged["mean_2"] + merged["std_2"] + + ax1.set_xscale("log", base=2) + ax1.set_yscale("log", base=2) + + ax1.legend(loc="upper left") + ax1.grid(True, which="both", linestyle="--", linewidth=0.5) + + xticks = grouped1["kb"].to_numpy() + xticks_filtered = [x for i, x in enumerate(xticks) if i % 2 == 0] + xtick_labels = [ + f"{int(x/1024)} MiB" if x >= 1024 else f"{int(x)} KiB" for x in xticks_filtered + ] + + plt.xticks(xticks_filtered, xtick_labels, rotation=45, ha="right") + + plt.title("Lower is better ↓", color="navy") + plt.ylabel("Time (ns - logarithmic scale)") + plt.xlabel("Memory size (logarithmic scale)") + + ax1.spines["top"].set_visible(False) + ax1.spines["right"].set_visible(False) + + plt.tight_layout() + + output = output_root / Path(f"result.{format}") + plt.savefig(output, format=format) diff --git a/archive/2024/winter/bsc_dichler/scripts/plot/contiguous_tagging.py b/archive/2024/winter/bsc_dichler/scripts/plot/contiguous_tagging.py new file mode 100644 index 000000000..df6a3eba1 --- /dev/null +++ b/archive/2024/winter/bsc_dichler/scripts/plot/contiguous_tagging.py @@ -0,0 +1,91 @@ +from pathlib import Path +import pandas as pd +import matplotlib.pyplot as plt +import numpy as np + + +def plot(output_root: Path, format): + output_root = output_root / Path("contiguous_tagging") + labels = ["malloc", "stg", "st2g", "ldg", "ldr", "str"] + csv_files = [ + output_root / Path("tag_malloc.csv"), + output_root / Path("tag_stg.csv"), + output_root / Path("tag_st2g.csv"), + output_root / Path("ldg.csv"), + output_root / Path("load.csv"), + output_root / Path("store.csv"), + ] + + dfs = [] + for file in csv_files: + df = pd.read_csv(file, sep=";") + df["duration"] = df["duration"] + + df["duration_per_op"] = df["duration"] / df["ops"] + g = df.groupby("size")["duration_per_op"].agg(["mean", "std"]).reset_index() + + dfs.append(g) + + _, ax1 = plt.subplots(figsize=(10, 6)) + + library = [""] + colors = [ + "#a6bddb", + "#fc9272", + "#99d8c9", + "#c994c7", + "#fdbb84", + "#efedf5", + "skyblue", + ] + bar_width = 0.8 / len(csv_files) + x = np.arange(len(library)) + + group_mins = {} + group_maxs = {} + + hatches = ["", "", "", "", "", "", ""] + for i in range(len(csv_files)): + df = dfs[i] + mean_values = df["mean"].values + + for j, size in enumerate(df["size"].values): + x_pos = x[j] + (i - (len(csv_files) - 1) / 2) * bar_width + ax1.text( + x_pos, + mean_values[j], + f"{mean_values[j]:.3f}", + ha="center", + va="bottom", + color="black", + ) + if size not in group_mins or mean_values[j] < group_mins[size][1]: + group_mins[size] = (x_pos, mean_values[j]) # Store (x, min mean) + if size not in group_maxs or mean_values[j] > group_maxs[size][1]: + group_maxs[size] = (x_pos, mean_values[j]) # Store (x, max mean) + + _ = ax1.bar( + x + (i - (len(csv_files) - 1) / 2) * bar_width, + mean_values, + yerr=df["std"], + width=bar_width, + capsize=5, + label=labels[i], + color=colors[i % len(colors)], + edgecolor="black", + hatch=hatches[i], + linewidth=2, + ) + + ax1.set_ylabel("Time (ns)") + ax1.set_xlabel("Single instruction") + ax1.legend(labels=labels, loc="upper right") + plt.title("Lower is better ↓", color="navy") + ax1.spines["top"].set_visible(False) + ax1.spines["right"].set_visible(False) + plt.xticks(x, library, ha="right") + ax1.set_ylim(ymin=0) + plt.tight_layout() + + output = output_root / Path(f"result.{format}") + plt.savefig(output, format=format) diff --git a/archive/2024/winter/bsc_dichler/scripts/plot/malloc.py b/archive/2024/winter/bsc_dichler/scripts/plot/malloc.py new file mode 100644 index 000000000..50a21aa18 --- /dev/null +++ b/archive/2024/winter/bsc_dichler/scripts/plot/malloc.py @@ -0,0 +1,122 @@ +from pathlib import Path +import pandas as pd +import matplotlib.pyplot as plt +import numpy as np + + +def run(csv_file1, csv_file2, duration_type, output, format): + df1 = pd.read_csv(csv_file1, sep=";") + df2 = pd.read_csv(csv_file2, sep=";") + + def norm(df): + df["duration_allocation"] = df["duration_allocation"] / df["allocation"] / 1000 + df["duration_deallocation"] = ( + df["duration_deallocation"] / df["allocation"] / 1000 + ) + + norm(df1) + norm(df2) + + grouped1 = ( + df1.groupby("size")[["duration_allocation", "duration_deallocation"]] + .agg(["mean", "std"]) + .reset_index() + ) + grouped2 = ( + df2.groupby("size")[["duration_allocation", "duration_deallocation"]] + .agg(["mean", "std"]) + .reset_index() + ) + + _, ax1 = plt.subplots(figsize=(12, 6)) + + library = [ + "16 Bytes", + "128 Bytes", + "256 Bytes", + "1024 Bytes", + "2048 Bytes", + "4096 Bytes", + "8192 Bytes", + ] + x = np.arange(len(library)) + bar_width = 0.35 + + bars1 = ax1.bar( + x - bar_width / 2, + grouped1[duration_type]["mean"], + yerr=grouped1[duration_type]["std"], + width=bar_width, + capsize=5, + label="MTE disabled", + color="#a6bddb", + edgecolor="black", + linewidth=2, + ) + bars2 = ax1.bar( + x + bar_width / 2, + grouped2[duration_type]["mean"], + yerr=grouped2[duration_type]["std"], + width=bar_width, + capsize=5, + label="MTE enabled", + color="#fc9272", + edgecolor="black", + linewidth=2, + ) + + for i in range(len(bars1)): + height2 = bars2[i].get_height() + height1 = bars1[i].get_height() + + ax1.annotate( + "", + xy=(x[i] - bar_width / 2, height2), + xytext=(x[i] - bar_width / 2, height1), + arrowprops=dict(arrowstyle="->", color="red", lw=2), + color="red", + ha="center", + ) + + difference = height2 / height1 + ax1.text( + i - bar_width / 2 - 0.04, + height1 + ((height2 - height1) / 2) - 0.08, + f"{difference:.2f}×", + color="red", + fontweight="bold", + bbox=dict(facecolor="white", alpha=1.0, edgecolor="none"), + ha="center", + ) + + plt.ylabel("Time (µs)") + ax1.set_xlabel("Batch size") + ax1.legend(loc="upper left") + plt.title("Lower is better ↓", color="navy") + + ax1.spines["top"].set_visible(False) + ax1.spines["right"].set_visible(False) + plt.tight_layout() + + plt.xticks(x, library) + plt.tight_layout() + plt.savefig(output, format=format) + + +def plot(output_root: Path, format): + output_root = output_root / Path("malloc") + + run( + output_root / Path("malloc.csv"), + output_root / Path("malloc_mte.csv"), + "duration_allocation", + output_root / Path(f"result-alloc.{format}"), + format, + ) + run( + output_root / Path("malloc.csv"), + output_root / Path("malloc_mte.csv"), + "duration_deallocation", + output_root / Path(f"result-dealloc.{format}"), + format, + ) diff --git a/archive/2024/winter/bsc_dichler/scripts/plot/non_contiguous.py b/archive/2024/winter/bsc_dichler/scripts/plot/non_contiguous.py new file mode 100644 index 000000000..ddfae4322 --- /dev/null +++ b/archive/2024/winter/bsc_dichler/scripts/plot/non_contiguous.py @@ -0,0 +1,99 @@ +from pathlib import Path +import pandas as pd +import matplotlib.pyplot as plt + + +def plot(output_root: Path, format): + output_root = output_root / Path("non_contiguous") + mte_enabled_csv = output_root / Path("load_mte.csv") + mte_disabled_csv = output_root / Path("load.csv") + + enabled_df = pd.read_csv(mte_enabled_csv, sep=";") + disabled_df = pd.read_csv(mte_disabled_csv, sep=";") + + for df in [enabled_df, disabled_df]: + df["duration"] = df["duration"] / 1_000_000 + df["kb"] = df["len"] * 16 // 1024 + + enabled_grouped = ( + enabled_df.groupby("kb")["duration"].agg(["mean", "std"]).reset_index() + ) + disabled_grouped = ( + disabled_df.groupby("kb")["duration"].agg(["mean", "std"]).reset_index() + ) + + _, ax1 = plt.subplots(figsize=(10, 6)) + ax1.errorbar( + enabled_grouped["kb"], + enabled_grouped["mean"], + yerr=enabled_grouped["std"], + capsize=5, + color="#a6bddb", + linewidth=2.5, + label="MTE enabled", + ) + ax1.errorbar( + disabled_grouped["kb"], + disabled_grouped["mean"], + yerr=disabled_grouped["std"], + capsize=5, + color="#fc9272", + linewidth=2.5, + label="MTE disabled", + ) + + ax1.set_xscale("log", base=2) + ax1.set_yscale("log", base=2) + + tick_positions = enabled_grouped["kb"].iloc[::2] + tick_labels = [ + f"{v} KiB" if v < 1024 else f"{v // 1024} MiB" for v in tick_positions + ] + ax1.set_xticks(tick_positions) + ax1.set_xticklabels(tick_labels, rotation=45, ha="right") + + plt.xticks() + plt.yticks() + + enabled_grouped["lower"] = enabled_grouped["mean"] - enabled_grouped["std"] + disabled_grouped["lower"] = disabled_grouped["mean"] - disabled_grouped["std"] + enabled_grouped["upper"] = enabled_grouped["mean"] + enabled_grouped["std"] + disabled_grouped["upper"] = disabled_grouped["mean"] + disabled_grouped["std"] + + overlap = (disabled_grouped["lower"] <= enabled_grouped["upper"]) & ( + disabled_grouped["upper"] >= enabled_grouped["lower"] + ) + + enabled_grouped["percentage_diff"] = ( + (enabled_grouped["mean"] - disabled_grouped["mean"]) / enabled_grouped["mean"] + ) * 100 + enabled_grouped.loc[overlap, "percentage_diff"] = 0 + + ax2 = ax1.twinx() + ax2.plot( + enabled_grouped["kb"], + enabled_grouped["percentage_diff"], + "r--", + label="% Difference", + ) + ax2.set_ylabel("Difference (%)", fontsize=12) + ax2.set_ylim( + min(enabled_grouped["percentage_diff"]), + max(enabled_grouped["percentage_diff"]) + 10, + ) + + h1, l1 = ax1.get_legend_handles_labels() + h2, l2 = ax2.get_legend_handles_labels() + + ax1.legend(loc="upper left", handles=h1 + h2, labels=l1 + l2) + + ax1.set_ylabel("Time (ns - logarithmic scale)") + ax1.set_xlabel("Memory size (logarithmic scale)") + + plt.title("Lower is better ↓", color="navy") + + ax1.grid(True, which="both", linestyle=":", linewidth=0.5) + plt.tight_layout() + + output = output_root / Path(f"result.{format}") + plt.savefig(output, format=format) diff --git a/archive/2024/winter/bsc_dichler/scripts/plot/parallel_non_contiguous.py b/archive/2024/winter/bsc_dichler/scripts/plot/parallel_non_contiguous.py new file mode 100644 index 000000000..f766fcedc --- /dev/null +++ b/archive/2024/winter/bsc_dichler/scripts/plot/parallel_non_contiguous.py @@ -0,0 +1,117 @@ +from pathlib import Path +import pandas as pd +import matplotlib.pyplot as plt + + +def run(csv_files: list[Path], output: Path, format): + _, ax1 = plt.subplots(figsize=(10, 6)) + labels = ["MTE disabled", "MTE enabled"] + + data = [] + unique_threads = set() + tick_positions = None + for file in csv_files: + df = pd.read_csv(file, sep=";") + df["duration"] = df["duration"] // 1_000 + g = ( + df.groupby(["len", "threads"])["duration"] + .agg(["mean", "std"]) + .reset_index() + ) + g["kb"] = (g["len"] * 16) / 1024 + data.append(g) + unique_threads.update(g["threads"].unique()) + tick_positions = g["kb"].unique() + + unique_threads = sorted(unique_threads) + + thread_colors = {1: "tomato", 2: "#56B4E9", 3: "#009E73", 4: "#E69F00"} + + line_styles = ["-", "--"] + + handles = [] + labels_legend = [] + + for thread in unique_threads: + for idx, g in enumerate(data): + subset = g[g["threads"] == thread] + if subset.empty: + continue + + line = ax1.errorbar( + subset["kb"], + subset["mean"], + yerr=subset["std"], + fmt="o", + linestyle=line_styles[idx], + capsize=5, + color=thread_colors.get(thread, "black"), + ) + + label = ( + f"1 Thread - {labels[idx]}" + if thread == 1 + else f"{thread} Threads - {labels[idx]}" + ) + handles.append(line[0]) + labels_legend.append(label) + + ax1.legend( + handles=handles, + labels=labels_legend, + ncol=2, + loc="upper left", + fancybox=True, + shadow=False, + ) + + ax1.set_xscale("log", base=2) + ax1.set_yscale("log", base=2) + + ax1.grid(True, which="both", linestyle="--", linewidth=0.5) + tick_labels = [] + xticks_filtered = [x for i, x in enumerate(tick_positions) if i % 2 == 0] + for idx, v in enumerate(xticks_filtered): + l = "" + if v < 1024: + if v < 1: + l = "1 KiB" + else: + l = f"{v} KiB" + else: + l = f"{v // 1024} MiB" + + tick_labels.append(l) + + ax1.set_xticks(xticks_filtered) + ax1.set_xticklabels(tick_labels, rotation=45, ha="right") + ax1.set_ylabel("Time (ns - logarithmic scale)") + ax1.set_xlabel("Memory size (logarithmic scale)") + + ax1.spines["top"].set_visible(False) + ax1.spines["right"].set_visible(False) + + plt.title("Lower is better ↓", color="navy") + plt.tight_layout() + plt.savefig(output, format=format) + + +def plot(output_root: Path, format): + output_root = output_root / Path("parallel_non_contiguous") + + run( + [ + output_root / Path("write.csv"), + output_root / Path("write_mte.csv"), + ], + output_root / Path(f"result-write.{format}"), + format, + ) + run( + [ + output_root / Path("load.csv"), + output_root / Path("load_mte.csv"), + ], + output_root / Path(f"result-read.{format}"), + format, + ) |