From dfcbf1b8be0ba2681d31466c536061461af02e3e Mon Sep 17 00:00:00 2001 From: Lutetium-Vanadium Date: Sat, 10 Jun 2023 16:28:53 +0800 Subject: [PATCH 1/2] Add algoDelta configuration for TugOfWar --- include/CPPAlgos/TugOfWarCPPAlgo.h | 12 +++++++----- src/CPPAlgos/TugOfWarCPPAlgo.cpp | 7 +++++++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/include/CPPAlgos/TugOfWarCPPAlgo.h b/include/CPPAlgos/TugOfWarCPPAlgo.h index 63e1692a..25c155d1 100644 --- a/include/CPPAlgos/TugOfWarCPPAlgo.h +++ b/include/CPPAlgos/TugOfWarCPPAlgo.h @@ -16,22 +16,24 @@ namespace AMMBench { /** * @class TugOfWarCPPAlgo CPPAlgos/TugOfWarCPPAlgo.h * @brief The tug of war class of c++ algoS + * @note parameters + * - algoDelta Double, the delta parameter in this algo, default 0.02 */ class TugOfWarCPPAlgo : public AMMBench::AbstractCPPAlgo { - double delta = 0.2; + double algoDelta = 0.02; public: TugOfWarCPPAlgo() { } - TugOfWarCPPAlgo(double delta) : delta(delta) { - - } - ~TugOfWarCPPAlgo() { } + /** + * @brief set the algo-specfic config related to one algorithm + */ + virtual void setConfig(INTELLI::ConfigMapPtr cfg); /** * @brief the virtual function provided for outside callers, rewrite in children classes diff --git a/src/CPPAlgos/TugOfWarCPPAlgo.cpp b/src/CPPAlgos/TugOfWarCPPAlgo.cpp index 54e0d592..1306612d 100644 --- a/src/CPPAlgos/TugOfWarCPPAlgo.cpp +++ b/src/CPPAlgos/TugOfWarCPPAlgo.cpp @@ -5,6 +5,10 @@ #include namespace AMMBench { +void TugOfWarCPPAlgo::setConfig(INTELLI::ConfigMapPtr cfg) { + algoDelta = cfg->tryDouble("algoDelta",algoDelta,true); +} + torch::Tensor TugOfWarCPPAlgo::generateTugOfWarMatrix(int64_t m, int64_t n) { double e = 1.0 / std::sqrt(m); torch::Tensor M = torch::randint(2, {m, n}); @@ -15,6 +19,9 @@ torch::Tensor TugOfWarCPPAlgo::amm(torch::Tensor A, torch::Tensor B, uint64_t l2 int64_t n = A.size(1); int64_t p = B.size(1); int64_t l = (int64_t) l2; + + double delta = algoDelta; + int64_t i_iters = static_cast(-std::log(delta)); int64_t j_iters = static_cast(2 * (-std::log(delta) + std::log(-std::log(delta)))); From 6552138427041bc78f66c2f08dfd72d3ce6c5328 Mon Sep 17 00:00:00 2001 From: Lutetium-Vanadium Date: Mon, 12 Jun 2023 12:54:29 +0800 Subject: [PATCH 2/2] Add scripts to scan beta and delta --- benchmark/scripts/scanAlgoBeta/OoOCommon.py | 125 ++++++ benchmark/scripts/scanAlgoBeta/accuBar.py | 328 ++++++++++++++++ benchmark/scripts/scanAlgoBeta/autoParase.py | 87 +++++ .../scripts/scanAlgoBeta/config_CPPBCOOFD.csv | 11 + .../scripts/scanAlgoBeta/config_RAWMM.csv | 9 + .../scripts/scanAlgoBeta/drawTogether.py | 178 +++++++++ benchmark/scripts/scanAlgoBeta/groupBar.py | 236 +++++++++++ benchmark/scripts/scanAlgoBeta/groupBar2.py | 232 +++++++++++ benchmark/scripts/scanAlgoBeta/groupLine.py | 366 ++++++++++++++++++ benchmark/scripts/scanAlgoBeta/perfRu.csv | 7 + benchmark/scripts/scanAlgoDelta/OoOCommon.py | 125 ++++++ benchmark/scripts/scanAlgoDelta/accuBar.py | 328 ++++++++++++++++ benchmark/scripts/scanAlgoDelta/autoParase.py | 87 +++++ .../scripts/scanAlgoDelta/config_CPPTOW.csv | 11 + .../scripts/scanAlgoDelta/config_RAWMM.csv | 9 + .../scripts/scanAlgoDelta/drawTogether.py | 177 +++++++++ benchmark/scripts/scanAlgoDelta/groupBar.py | 236 +++++++++++ benchmark/scripts/scanAlgoDelta/groupBar2.py | 232 +++++++++++ benchmark/scripts/scanAlgoDelta/groupLine.py | 366 ++++++++++++++++++ benchmark/scripts/scanAlgoDelta/perfRu.csv | 7 + figures/algoBeta/algoBeta_cacheMiss.pdf | Bin 0 -> 7700 bytes figures/algoBeta/algoBeta_ebRatio.pdf | Bin 0 -> 7456 bytes figures/algoBeta/algoBeta_elapsedTime.pdf | Bin 0 -> 7725 bytes figures/algoBeta/algoBeta_froError.pdf | Bin 0 -> 7522 bytes figures/algoDelta/algoDelta_cacheMiss.pdf | Bin 0 -> 8432 bytes figures/algoDelta/algoDelta_ebRatio.pdf | Bin 0 -> 8330 bytes figures/algoDelta/algoDelta_elapsedTime.pdf | Bin 0 -> 8710 bytes figures/algoDelta/algoDelta_froError.pdf | Bin 0 -> 8344 bytes 28 files changed, 3157 insertions(+) create mode 100755 benchmark/scripts/scanAlgoBeta/OoOCommon.py create mode 100755 benchmark/scripts/scanAlgoBeta/accuBar.py create mode 100755 benchmark/scripts/scanAlgoBeta/autoParase.py create mode 100644 benchmark/scripts/scanAlgoBeta/config_CPPBCOOFD.csv create mode 100644 benchmark/scripts/scanAlgoBeta/config_RAWMM.csv create mode 100755 benchmark/scripts/scanAlgoBeta/drawTogether.py create mode 100755 benchmark/scripts/scanAlgoBeta/groupBar.py create mode 100755 benchmark/scripts/scanAlgoBeta/groupBar2.py create mode 100755 benchmark/scripts/scanAlgoBeta/groupLine.py create mode 100644 benchmark/scripts/scanAlgoBeta/perfRu.csv create mode 100755 benchmark/scripts/scanAlgoDelta/OoOCommon.py create mode 100755 benchmark/scripts/scanAlgoDelta/accuBar.py create mode 100755 benchmark/scripts/scanAlgoDelta/autoParase.py create mode 100644 benchmark/scripts/scanAlgoDelta/config_CPPTOW.csv create mode 100644 benchmark/scripts/scanAlgoDelta/config_RAWMM.csv create mode 100755 benchmark/scripts/scanAlgoDelta/drawTogether.py create mode 100755 benchmark/scripts/scanAlgoDelta/groupBar.py create mode 100755 benchmark/scripts/scanAlgoDelta/groupBar2.py create mode 100755 benchmark/scripts/scanAlgoDelta/groupLine.py create mode 100644 benchmark/scripts/scanAlgoDelta/perfRu.csv create mode 100644 figures/algoBeta/algoBeta_cacheMiss.pdf create mode 100644 figures/algoBeta/algoBeta_ebRatio.pdf create mode 100644 figures/algoBeta/algoBeta_elapsedTime.pdf create mode 100644 figures/algoBeta/algoBeta_froError.pdf create mode 100644 figures/algoDelta/algoDelta_cacheMiss.pdf create mode 100644 figures/algoDelta/algoDelta_ebRatio.pdf create mode 100644 figures/algoDelta/algoDelta_elapsedTime.pdf create mode 100644 figures/algoDelta/algoDelta_froError.pdf diff --git a/benchmark/scripts/scanAlgoBeta/OoOCommon.py b/benchmark/scripts/scanAlgoBeta/OoOCommon.py new file mode 100755 index 00000000..70f4cf33 --- /dev/null +++ b/benchmark/scripts/scanAlgoBeta/OoOCommon.py @@ -0,0 +1,125 @@ +import csv +import numpy as np +import matplotlib.pyplot as plt +import itertools as it +import os + +import matplotlib +import matplotlib.pyplot as plt +import numpy as np +import pylab +from matplotlib.font_manager import FontProperties +from matplotlib.ticker import LogLocator, LinearLocator +import os +import pandas as pd +import sys +import matplotlib.ticker as mtick + +OPT_FONT_NAME = 'Helvetica' +TICK_FONT_SIZE = 22 +LABEL_FONT_SIZE = 28 +LEGEND_FONT_SIZE = 30 +LABEL_FP = FontProperties(style='normal', size=LABEL_FONT_SIZE) +LEGEND_FP = FontProperties(style='normal', size=LEGEND_FONT_SIZE) +TICK_FP = FontProperties(style='normal', size=TICK_FONT_SIZE) + +MARKERS = (['*', '|', 'v', "^", "", "h", "<", ">", "+", "d", "<", "|", "", "+", "_"]) +# you may want to change the color map for different figures +COLOR_MAP = ( + '#B03A2E', '#2874A6', '#239B56', '#7D3C98', '#FFFFFF', '#F1C40F', '#F5CBA7', '#82E0AA', '#AEB6BF', '#AA4499') +# you may want to change the patterns for different figures +PATTERNS = (["////", "o", "", "||", "-", "//", "\\", "o", "O", "////", ".", "|||", "o", "---", "+", "\\\\", "*"]) +LABEL_WEIGHT = 'bold' +LINE_COLORS = COLOR_MAP +LINE_WIDTH = 3.0 +MARKER_SIZE = 15.0 +MARKER_FREQUENCY = 1000 + + +def editConfig(src, dest, key, value): + df = pd.read_csv(src, header=None) + rowIdx = 0 + idxt = 0 + for cell in df[0]: + # print(cell) + if (cell == key): + rowIdx = idxt + break + idxt = idxt + 1 + df[1][rowIdx] = str(value) + df.to_csv(dest, index=False, header=False) + + +def readConfig(src, key): + df = pd.read_csv(src, header=None) + rowIdx = 0 + idxt = 0 + for cell in df[0]: + # print(cell) + if (cell == key): + rowIdx = idxt + break + idxt = idxt + 1 + return df[1][rowIdx] + + +def draw2yLine(NAME, Com, R1, R2, l1, l2, m1, m2, fname): + fig, ax1 = plt.subplots(figsize=(10, 6.4)) + lines = [None] * 2 + # ax1.set_ylim(0, 1) + print(Com) + print(R1) + lines[0], = ax1.plot(Com, R1, color=LINE_COLORS[0], \ + linewidth=LINE_WIDTH, marker=MARKERS[0], \ + markersize=MARKER_SIZE + # + ) + + # plt.show() + ax1.set_ylabel(m1, fontproperties=LABEL_FP) + ax1.set_xlabel(NAME, fontproperties=LABEL_FP) + # ax1.set_xticklabels(ax1.get_xticklabels()) # 设置共用的x轴 + plt.xticks(rotation=0, size=TICK_FONT_SIZE) + plt.yticks(rotation=0, size=TICK_FONT_SIZE) + plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号 + ax2 = ax1.twinx() + + # ax2.set_ylabel('latency/us') + # ax2.set_ylim(0, 0.5) + lines[1], = ax2.plot(Com, R2, color=LINE_COLORS[1], \ + linewidth=LINE_WIDTH, marker=MARKERS[1], \ + markersize=MARKER_SIZE) + + ax2.set_ylabel(m2, fontproperties=LABEL_FP) + # ax2.vlines(192000, min(R2)-1, max(R2)+1, colors = "GREEN", linestyles = "dashed",label='total L1 size') + # plt.grid(axis='y', color='gray') + + # style = dict(size=10, color='black') + # ax2.hlines(tset, 0, x2_list[len(x2_list)-1]+width, colors = "r", linestyles = "dashed",label="tset") + # ax2.text(4, tset, "$T_{set}$="+str(tset)+"us", ha='right', **style) + + # plt.xlabel('batch', fontproperties=LABEL_FP) + + # plt.xscale('log') + # figure.xaxis.set_major_locator(LinearLocator(5)) + ax1.yaxis.set_major_locator(LinearLocator(5)) + ax2.yaxis.set_major_locator(LinearLocator(5)) + ax1.yaxis.set_major_formatter(mtick.FormatStrFormatter('%.1f')) + ax2.yaxis.set_major_formatter(mtick.FormatStrFormatter('%.1f')) + ax1.yaxis.set_major_formatter(mtick.FormatStrFormatter('%.1f')) + ax2.yaxis.set_major_formatter(mtick.FormatStrFormatter('%.1f')) + plt.legend(lines, + [l1, l2], + prop=LEGEND_FP, + loc='upper center', + ncol=1, + bbox_to_anchor=(0.55, 1.3 + ), shadow=False, + columnspacing=0.1, + frameon=True, borderaxespad=-1.5, handlelength=1.2, + handletextpad=0.1, + labelspacing=0.1) + plt.yticks(rotation=0, size=TICK_FONT_SIZE) + plt.tight_layout() + + plt.savefig(fname + ".pdf") diff --git a/benchmark/scripts/scanAlgoBeta/accuBar.py b/benchmark/scripts/scanAlgoBeta/accuBar.py new file mode 100755 index 00000000..638c8a60 --- /dev/null +++ b/benchmark/scripts/scanAlgoBeta/accuBar.py @@ -0,0 +1,328 @@ +import getopt +import os +import sys + +import matplotlib +import matplotlib.pyplot as plt +import numpy as np +import pylab +from matplotlib.font_manager import FontProperties +from matplotlib.ticker import LinearLocator, LogLocator, MaxNLocator, ScalarFormatter +from numpy import double + +OPT_FONT_NAME = 'Helvetica' +TICK_FONT_SIZE = 24 +LABEL_FONT_SIZE = 28 +LEGEND_FONT_SIZE = 26 +TITLE_FRONT_SIZE = 32 +LABEL_FP = FontProperties(style='normal', size=LABEL_FONT_SIZE) +LEGEND_FP = FontProperties(style='normal', size=LEGEND_FONT_SIZE) +TICK_FP = FontProperties(style='normal', size=TICK_FONT_SIZE) +TITLE_FP = FontProperties(style='normal', size=TITLE_FRONT_SIZE) +MARKERS = (['o', 's', 'v', "^", "h", "v", ">", "x", "d", "<", "|", "", "|", "_"]) +# you may want to change the color map for different figures +COLOR_MAP = ('#B03A2E', '#2874A6', '#239B56', '#7D3C98', '#F1C40F', '#F5CBA7', '#82E0AA', '#AEB6BF', '#AA4499') +# you may want to change the patterns for different figures +PATTERNS = (["\\", "///", "o", "||", "\\\\", "\\\\", "//////", "//////", ".", "\\\\\\", "\\\\\\"]) +LABEL_WEIGHT = 'bold' +LINE_COLORS = COLOR_MAP +LINE_WIDTH = 3.0 +MARKER_SIZE = 0.0 +MARKER_FREQUENCY = 1000 + +matplotlib.rcParams['ps.useafm'] = True +matplotlib.rcParams['pdf.use14corefonts'] = True +matplotlib.rcParams['xtick.labelsize'] = TICK_FONT_SIZE +matplotlib.rcParams['ytick.labelsize'] = TICK_FONT_SIZE +matplotlib.rcParams['font.family'] = OPT_FONT_NAME +matplotlib.rcParams['pdf.fonttype'] = 42 + +exp_dir = "/data1/xtra" + +FIGURE_FOLDER = exp_dir + '/results/figure' + + +# there are some embedding problems if directly exporting the pdf figure using matplotlib. +# so we generate the eps format first and convert it to pdf. +def ConvertEpsToPdf(dir_filename): + os.system("epstopdf --outfile " + dir_filename + ".pdf " + dir_filename + ".eps") + os.system("rm -rf " + dir_filename + ".eps") + + +class ScalarFormatterForceFormat(ScalarFormatter): + def _set_format(self): # Override function that finds format to use. + self.format = "%1.1f" # Give format here + + +# draw a line chart +def DrawFigure(x_values, y_values, legend_labels, x_label, y_label, filename, allow_legend, title): + # you may change the figure size on your own. + + fig = plt.figure(figsize=(16, 9)) + figure = fig.add_subplot(111) + + FIGURE_LABEL = legend_labels + + # if not os.path.exists(FIGURE_FOLDER): + # os.makedirs(FIGURE_FOLDER) + + # values in the x_xis + index = np.arange(len(x_values)) + # the bar width. + # you may need to tune it to get the best figure. + width = 0.5 + # draw the bars + bottom_base = np.zeros(len(y_values[0])) + bars = [None] * (len(FIGURE_LABEL)) + for i in range(len(y_values)): + bars[i] = plt.bar(index + width / 2, y_values[i], width, hatch=PATTERNS[i], color=LINE_COLORS[i], + label=FIGURE_LABEL[i], bottom=bottom_base, edgecolor='black', linewidth=3) + bottom_base = np.array(y_values[i]) + bottom_base + + # sometimes you may not want to draw legends. + if allow_legend == True: + plt.legend(bars, FIGURE_LABEL + # mode='expand', + # shadow=False, + # columnspacing=0.25, + # labelspacing=-2.2, + # borderpad=5, + # bbox_transform=ax.transAxes, + # frameon=False, + # columnspacing=5.5, + # handlelength=2, + ) + if allow_legend == True: + handles, labels = figure.get_legend_handles_labels() + if allow_legend == True: + leg = plt.legend(handles[::-1], labels[::-1], + loc='upper center', + # prop=#LEGEND_FP, + # ncol=3, + # bbox_to_anchor=(0.5, 1.25), + # bbox_to_anchor=(1.17, 0.5), + # handletextpad=0.1, + # borderaxespad=0.0, + # handlelength=1.8, + # labelspacing=0.3, + # columnspacing=0.3, + ) + leg.get_frame().set_linewidth(2) + leg.get_frame().set_edgecolor("black") + + # you may need to tune the xticks position to get the best figure. + plt.xticks(index + 0.6 * width, x_values) + yfmt = ScalarFormatterForceFormat() + yfmt.set_powerlimits((0, 0)) + figure.get_yaxis().set_major_formatter(yfmt) + plt.ticklabel_format(axis="y", style="sci", scilimits=(0, 0), useMathText=True) + plt.grid(axis='y', color='gray') + figure.yaxis.set_major_locator(LinearLocator(3)) + # figure.yaxis.set_major_locator(LogLocator(base=10)) + # figure.yaxis.set_major_locator(LinearLocator(6)) + + figure.get_xaxis().set_tick_params(direction='in', pad=10) + figure.get_yaxis().set_tick_params(direction='in', pad=10) + + plt.xlabel(x_label, fontproperties=LABEL_FP) + plt.ylabel(y_label, fontproperties=LABEL_FP) + + size = fig.get_size_inches() + dpi = fig.get_dpi() + plt.title(title, fontproperties=TITLE_FP) + plt.savefig(filename + ".pdf", bbox_inches='tight', format='pdf') + + +def DrawLegend(legend_labels, filename): + fig = pylab.figure() + ax1 = fig.add_subplot(111) + FIGURE_LABEL = legend_labels + LEGEND_FP = FontProperties(style='normal', size=26) + + bars = [None] * (len(FIGURE_LABEL)) + data = [1] + x_values = [1] + + width = 0.3 + for i in range(len(FIGURE_LABEL)): + bars[i] = ax1.bar(x_values, data, width, hatch=PATTERNS[i], color=LINE_COLORS[i], + linewidth=0.2) + + # LEGEND + figlegend = pylab.figure(figsize=(11, 0.5)) + figlegend.legend(bars, FIGURE_LABEL, prop=LEGEND_FP, \ + loc=9, + bbox_to_anchor=(0, 0.4, 1, 1), + ncol=len(FIGURE_LABEL), mode="expand", shadow=False, \ + frameon=False, handlelength=1.1, handletextpad=0.2, columnspacing=0.1) + + figlegend.savefig(FIGURE_FOLDER + '/' + filename + '.pdf') + + +def normalize(y_values): + y_total_values = np.zeros(len(y_values[0])) + + for i in range(len(y_values)): + y_total_values += np.array(y_values[i]) + y_norm_values = [] + + for i in range(len(y_values)): + y_norm_values.append(np.array(y_values[i]) / (y_total_values) * 100) + return y_norm_values + + +# example for reading csv file +def ReadFile(id): + # Creates a list containing w lists, each of h items, all set to 0 + w, h = 5, 3 + y = [[0 for x in range(w)] for y in range(h)] + # print(matches) + max_value = 0 + j = 0 + bound = id + 1 * w + for i in range(id, bound, 1): + cnt = 0 + print(i) + f = open(exp_dir + "/results/breakdown/PMJ_JBCR_NP_{}.txt".format(i), "r") + read = f.readlines() + others = 0 + for x in read: + value = double(x.strip("\n")) + if value > max_value: + max_value = value + elif cnt == 3: # sort + y[0][j] = value + elif cnt == 4: # merge + y[1][j] = value + elif cnt == 5: # join + y[2][j] = value + else: + others += value + # if cnt == 6: + # y[2][j] = others + cnt += 1 + j += 1 + print(y) + return y, max_value + + +if __name__ == "__main__": + id = 119 + try: + opts, args = getopt.getopt(sys.argv[1:], '-i:h', ['test id', 'help']) + except getopt.GetoptError: + print('breakdown.py -id testid') + sys.exit(2) + for opt, opt_value in opts: + if opt in ('-h', '--help'): + print("[*] Help info") + exit() + elif opt == '-i': + print('Test ID:', opt_value) + id = (int)(opt_value) + + x_values = ['10%', '20%', '30%', '40%', '50%'] # sorting step size + + y_values, max_value = ReadFile(id) # 55 + + # y_norm_values = normalize(y_values) + + # break into 4 parts + legend_labels = ['sort', 'merge', 'join'] # , 'others' + + DrawFigure(x_values, y_values, legend_labels, + 'sorting step size', 'cycles per input tuple', + 'breakdown_sort_figure', True) + + # DrawLegend(legend_labels, 'breakdown_radix_legend') + + +def DrawPercentageFigure(x_values, y_values, legend_labels, x_label, y_label, filename, allow_legend, title): + # you may change the figure size on your own. + fig = plt.figure(figsize=(9, 3)) + figure = fig.add_subplot(111) + + FIGURE_LABEL = legend_labels + + # values in the x_xis + index = np.arange(len(x_values)) + # the bar width. + # you may need to tune it to get the best figure. + width = 0.5 + # draw the bars + bottom_base = np.zeros(len(y_values[0])) + bars = [None] * (len(FIGURE_LABEL)) + for i in range(len(y_values)): + bars[i] = plt.bar(index + width / 2, y_values[i], width, hatch=PATTERNS[i], color=LINE_COLORS[i], + label=FIGURE_LABEL[i], bottom=bottom_base, edgecolor='black', linewidth=3) + bottom_base = np.array(y_values[i]) + bottom_base + + # sometimes you may not want to draw legends. + if allow_legend == True: + plt.legend(bars, FIGURE_LABEL + # mode='expand', + # shadow=False, + # columnspacing=0.25, + # labelspacing=-2.2, + # borderpad=5, + # bbox_transform=ax.transAxes, + # frameon=False, + # columnspacing=5.5, + # handlelength=2, + ) + if allow_legend == True: + handles, labels = figure.get_legend_handles_labels() + if allow_legend == True: + print(handles[::-1], labels[::-1]) + leg = plt.legend(handles[::-1], labels[::-1], + loc='center', + prop=LEGEND_FP, + ncol=3, + bbox_to_anchor=(0.5, 1.2), + handletextpad=0.1, + borderaxespad=0.0, + handlelength=1.8, + labelspacing=0.3, + columnspacing=0.3, + ) + leg.get_frame().set_linewidth(2) + leg.get_frame().set_edgecolor("black") + + # sometimes you may not want to draw legends. + # if allow_legend == True: + # leg=plt.legend(bars, + # FIGURE_LABEL, + # prop=LEGEND_FP, + # loc='right', + # ncol=1, + # # mode='expand', + # bbox_to_anchor=(0.45, 1.1), shadow=False, + # columnspacing=0.1, + # frameon=True, borderaxespad=0.0, handlelength=1.5, + # handletextpad=0.1, + # labelspacing=0.1) + # leg.get_frame().set_linewidth(2) + # leg.get_frame().set_edgecolor("black") + + plt.ylim(0, 100) + + # you may need to tune the xticks position to get the best figure. + plt.xticks(index + 0.5 * width, x_values) + plt.xticks(rotation=30) + + # plt.xlim(0,) + # plt.ylim(0,1) + + plt.grid(axis='y', color='gray') + figure.yaxis.set_major_locator(LinearLocator(6)) + + figure.get_xaxis().set_tick_params(direction='in', pad=10) + figure.get_yaxis().set_tick_params(direction='in', pad=10) + + plt.xlabel(x_label, fontproperties=LABEL_FP) + plt.ylabel(y_label, fontproperties=LABEL_FP) + + size = fig.get_size_inches() + dpi = fig.get_dpi() + + plt.savefig(filename + ".pdf", bbox_inches='tight', format='pdf') diff --git a/benchmark/scripts/scanAlgoBeta/autoParase.py b/benchmark/scripts/scanAlgoBeta/autoParase.py new file mode 100755 index 00000000..9375c8e0 --- /dev/null +++ b/benchmark/scripts/scanAlgoBeta/autoParase.py @@ -0,0 +1,87 @@ +import csv + + +def paraseValidStageNames(a): + nameList = [] + with open(a, 'r') as f: + reader = csv.reader(f) + # reader = [each for each in csv.DictReader(f, delimiter=',')] + result = list(reader) + rows = len(result) + # print('rows=',rows) + firstRow = result[0] + # print(firstRow) + index = 0 + # define what may attract our interest + idxCpu = 0 + idxName = 0 + for i in firstRow: + # print(i) + if (i == 'cpu'): + idxCpu = index + if (i == 'name'): + idxName = index + index = index + 1 + # read the valid stages + vdataEntries = 0 + + for k in range(1, rows): + if (result[k][idxCpu] != 'NA'): + R1 = ((result[k][idxName])) + nameList.append(R1) + return nameList + + +def paraseValidColums(a, nameList, colTitle): + with open(a, 'r') as f: + reader = csv.reader(f) + # reader = [each for each in csv.DictReader(f, delimiter=',')] + result = list(reader) + rows = len(result) + # print('rows=',rows) + firstRow = result[0] + # print(firstRow) + index = 0 + # define what may attract our interest + idxCpu = 0 + idxName = 0 + idxTitle = 0 + for i in firstRow: + # print(i) + if (i == 'cpu'): + idxCpu = index + if (i == 'name'): + idxName = index + if (i == colTitle): + idxTitle = index + index = index + 1 + # read the valid stages + vdataEntries = 0 + ru = [] + for k in range(1, rows): + if (result[k][idxCpu] != 'NA'): + R1 = ((result[k][idxName])) + for j in range(len(nameList)): + if (R1 == nameList[j]): + s = int(result[k][idxTitle]) + ru.append(s) + break + return ru + + +def maxInList(a): + # a in [[1,2] [3,4]] + inLen = len(a[0]) + ru = [] + index = [] + ti = 0 + for i in range(len(a[0])): + ts = 0 + ti = 0 + for k in range(len(a)): + if (a[k][i] > ts): + ts = a[k][i] + ti = k + ru.append(ts) + index.append(ti) + return ru, index diff --git a/benchmark/scripts/scanAlgoBeta/config_CPPBCOOFD.csv b/benchmark/scripts/scanAlgoBeta/config_CPPBCOOFD.csv new file mode 100644 index 00000000..3db65119 --- /dev/null +++ b/benchmark/scripts/scanAlgoBeta/config_CPPBCOOFD.csv @@ -0,0 +1,11 @@ +key,value,type +aRow,100,U64 +aCol,1000,U64 +bCol,500,U64 +sketchDimension,25,U64 +ptFile,torchscripts/BetaCoOccurringFD.pt,String +useCPP,1,U64 +cppAlgoTag,bcooFD,String +threads,1,U64 +forceMP,1,U64 +algoBeta,1.0,Double diff --git a/benchmark/scripts/scanAlgoBeta/config_RAWMM.csv b/benchmark/scripts/scanAlgoBeta/config_RAWMM.csv new file mode 100644 index 00000000..db4593f3 --- /dev/null +++ b/benchmark/scripts/scanAlgoBeta/config_RAWMM.csv @@ -0,0 +1,9 @@ +key,value,type +aRow,1000,U64 +aCol,1000,U64 +bCol,500,U64 +sketchDimension,25,U64 +ptFile,torchscripts/RAWMM.pt,String +threads,1,U64 +forceMP,1,U64 +algoBeta,1.0,Double diff --git a/benchmark/scripts/scanAlgoBeta/drawTogether.py b/benchmark/scripts/scanAlgoBeta/drawTogether.py new file mode 100755 index 00000000..203b84f4 --- /dev/null +++ b/benchmark/scripts/scanAlgoBeta/drawTogether.py @@ -0,0 +1,178 @@ +#!/usr/bin/env python3 +import csv +import numpy as np +import accuBar as accuBar +import groupBar as groupBar +import groupBar2 as groupBar2 +import groupLine as groupLine +from autoParase import * +import itertools as it +import os + +import matplotlib +import numpy as np +import pylab +import matplotlib.font_manager as fm +from matplotlib.font_manager import FontProperties +from matplotlib.ticker import LogLocator, LinearLocator +import os +import pandas as pd +import sys +from OoOCommon import * +import time + +# OPT_FONT_NAME = 'Helvetica' +TICK_FONT_SIZE = 22 +LABEL_FONT_SIZE = 28 +LEGEND_FONT_SIZE = 30 +LABEL_FP = FontProperties(style='normal', size=LABEL_FONT_SIZE) +LEGEND_FP = FontProperties(style='normal', size=LEGEND_FONT_SIZE) +TICK_FP = FontProperties(style='normal', size=TICK_FONT_SIZE) + +MARKERS = (['*', '|', 'v', "^", "", "h", "<", ">", "+", "d", "<", "|", "", "+", "_"]) +# you may want to change the color map for different figures +COLOR_MAP = ( + '#B03A2E', '#2874A6', '#239B56', '#7D3C98', '#FFFFFF', '#F1C40F', '#F5CBA7', '#82E0AA', '#AEB6BF', '#AA4499') +# you may want to change the patterns for different figures +PATTERNS = (["////", "o", "", "||", "-", "//", "\\", "o", "O", "////", ".", "|||", "o", "---", "+", "\\\\", "*"]) +LABEL_WEIGHT = 'bold' +LINE_COLORS = COLOR_MAP +LINE_WIDTH = 3.0 +MARKER_SIZE = 15.0 +MARKER_FREQUENCY = 1000 + +matplotlib.rcParams['ps.useafm'] = True +matplotlib.rcParams['pdf.use14corefonts'] = True +matplotlib.rcParams['xtick.labelsize'] = TICK_FONT_SIZE +matplotlib.rcParams['ytick.labelsize'] = TICK_FONT_SIZE +matplotlib.rcParams['font.family'] = OPT_FONT_NAME +matplotlib.rcParams['pdf.fonttype'] = 42 + +scanTag = "algoBeta" + + +def singleRun(exePath, singleValue, resultPath, configTemplate): + # resultFolder="singleValueTests" + configFname = "config_" + scanTag + str(singleValue) + ".csv" + # configTemplate = "config.csv" + # clear old files + os.system("cd " + exePath + "&& sudo rm *.csv") + + # editConfig(configTemplate, exePath + configFname, "earlierEmitMs", 0) + editConfig(configTemplate, exePath + configFname, scanTag, singleValue) + # prepare new file + # run + os.system("cd " + exePath + "&& sudo ./benchmark " + configFname) + # copy result + os.system("sudo rm -rf " + resultPath + "/" + str(singleValue)) + os.system("sudo mkdir " + resultPath + "/" + str(singleValue)) + os.system("cd " + exePath + "&& sudo cp *.csv " + resultPath + "/" + str(singleValue)) + + +def runScanVector(exePath, singleValueVec, resultPath, templateName="config.csv"): + for i in singleValueVec: + singleRun(exePath, i, resultPath, templateName) + + +def readResultSingle(singleValue, resultPath): + resultFname = resultPath + "/" + str(singleValue) + "/default.csv" + elapsedTime = readConfig(resultFname, "perfElapsedTime") + cacheMiss = readConfig(resultFname, "cacheMiss") + cacheRefs = readConfig(resultFname, "cacheRefs") + froError = readConfig(resultFname, "froError") + errorBoundRatio = readConfig(resultFname, "errorBoundRatio") + return elapsedTime, cacheMiss, cacheRefs, froError, errorBoundRatio + + +def cleanPath(path): + os.system("sudo rm -rf " + path) + os.system("sudo mkdir " + path) + + +def readResultVector(singleValueVec, resultPath): + elapseTimeVec = [] + cacheMissVec = [] + cacheRefVec = [] + froErrorVec = [] + errorBoundRatioVec = [] + for i in singleValueVec: + elapsedTime, cacheMiss, cacheRefs, froError, errorBoundRatio = readResultSingle(i, resultPath) + elapseTimeVec.append(float(elapsedTime) / 1000.0) + cacheMissVec.append(float(cacheMiss)) + cacheRefVec.append(float(cacheRefs)) + froErrorVec.append(float(froError)) + errorBoundRatioVec.append(float(errorBoundRatio)) + return np.array(elapseTimeVec), np.array(cacheMissVec), np.array(cacheRefVec), np.array(froErrorVec), np.array( + errorBoundRatioVec) + + +def compareMethod(exeSpace, commonPathBase, resultPaths, csvTemplates, periodVec, reRun=1): + elapsedTimeAll = [] + cacheMissAll = [] + cacheRefAll = [] + periodAll = [] + froAll = [] + errorBoundRatioAll = [] + for i in range(len(csvTemplates)): + resultPath = commonPathBase + resultPaths[i] + if (reRun == 1): + os.system("sudo rm -rf " + resultPath) + os.system("sudo mkdir " + resultPath) + runScanVector(exeSpace, periodVec, resultPath, csvTemplates[i]) + elapsedTime, cacheMiss, cacheRef, fro, eb = readResultVector(periodVec, resultPath) + elapsedTimeAll.append(elapsedTime) + cacheMissAll.append(cacheMiss) + cacheRefAll.append(cacheRef) + periodAll.append(periodVec) + cacheMissRateAll = np.array(cacheMissAll) / np.array(cacheRefAll) * 100.0 + froAll.append(fro) + errorBoundRatioAll.append(eb) + # periodAll.append(periodVec) + return np.array(elapsedTimeAll), cacheMissRateAll, periodAll, np.array(froAll), np.array(errorBoundRatioAll) + + +def main(): + exeSpace = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/" + commonBase = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/results/" + scanTag + "/" + figPath = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/figures/" + scanTag + methodTags = ["BCo-AMM", "MM"] + resultPaths = ["co", "mm"] + csvTemplates = ["config_CPPBCOOFD.csv", "config_RAWMM.csv"] + valueVec = [1.0, 5.0, 10.0, 15.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 88.0] + valueVecDisp = np.array(valueVec) + # run + reRun = 0 + if (len(sys.argv) < 2): + os.system("mkdir ../../results") + os.system("mkdir ../../figures") + os.system("mkdir " + figPath) + os.system("sudo rm -rf " + commonBase) + os.system("sudo mkdir " + commonBase) + reRun = 1 + + elapsedTimeAll, cacheMissAll, periodAll,fro,eb = compareMethod(exeSpace, commonBase, resultPaths, csvTemplates, valueVec, + reRun) + groupLine.DrawFigure(periodAll, elapsedTimeAll, + methodTags, + "value of beta", "elapsed time (ms)", 0, 1, + figPath + "/" + scanTag + "_elapsedTime", + True) + groupLine.DrawFigureYnormal(periodAll, cacheMissAll, + methodTags, + "value of beta", "cacheMiss (%)", 0, 1, + figPath + "/" + scanTag + "_cacheMiss", + True) + groupLine.DrawFigureYnormal(periodAll, + fro * 100.0, + methodTags, + "value of beta", "normalized error %", 0, 1, figPath + "/" +scanTag + "_froError", + True) + groupLine.DrawFigureYnormal(periodAll, + eb * 100.0, + methodTags, + "value of beta", "error bound ratio %", 0, 1, figPath + "/" + scanTag + "_ebRatio", + True) + + +if __name__ == "__main__": + main() diff --git a/benchmark/scripts/scanAlgoBeta/groupBar.py b/benchmark/scripts/scanAlgoBeta/groupBar.py new file mode 100755 index 00000000..ef2d9842 --- /dev/null +++ b/benchmark/scripts/scanAlgoBeta/groupBar.py @@ -0,0 +1,236 @@ +import itertools as it +import os + +import matplotlib +import matplotlib.pyplot as plt +import numpy as np +import pylab +from matplotlib.font_manager import FontProperties +from matplotlib.ticker import LogLocator, LinearLocator + +OPT_FONT_NAME = 'Helvetica' +TICK_FONT_SIZE = 24 +LABEL_FONT_SIZE = 28 +LEGEND_FONT_SIZE = 15 +LABEL_FP = FontProperties(style='normal', size=LABEL_FONT_SIZE) +LEGEND_FP = FontProperties(style='normal', size=LEGEND_FONT_SIZE) +TICK_FP = FontProperties(style='normal', size=TICK_FONT_SIZE) + +MARKERS = (["", 'o', 's', 'v', "^", "", "h", "<", ">", "+", "d", "<", "|", "", "+", "_"]) +# you may want to change the color map for different figures +COLOR_MAP = ( + '#7FFFFF', '#B03A2E', '#2874A6', '#FFFFFF', '#7FFFFF', '#B03A2E', '#2874A6', '#FFFFFF', '#F5CBA7', '#82E0AA', + '#AEB6BF', + '#AA4499') +# you may want to change the patterns for different figures +PATTERNS = ( + ["////", "\\\\", "//", "o", "*", "||", "-", "//", "\\", "o", "O", "////", ".", "|||", "o", "---", "+", "\\\\", "*"]) +LABEL_WEIGHT = 'bold' +LINE_COLORS = COLOR_MAP +LINE_WIDTH = 3.0 +MARKER_SIZE = 15.0 +MARKER_FREQUENCY = 1000 + +matplotlib.rcParams['ps.useafm'] = True +matplotlib.rcParams['pdf.use14corefonts'] = True +matplotlib.rcParams['xtick.labelsize'] = TICK_FONT_SIZE +matplotlib.rcParams['ytick.labelsize'] = TICK_FONT_SIZE +matplotlib.rcParams['font.family'] = OPT_FONT_NAME +matplotlib.rcParams['pdf.fonttype'] = 42 + +exp_dir = "/data1/xtra" + +FIGURE_FOLDER = exp_dir + '/results/figure' + + +def DrawLegend(legend_labels, filename): + fig = pylab.figure() + ax1 = fig.add_subplot(111) + FIGURE_LABEL = legend_labels + LEGEND_FP = FontProperties(style='normal', size=26) + figlegend = pylab.figure(figsize=(16, 0.5)) + bars = [None] * (len(FIGURE_LABEL)) + data = [1] + x_values = [1] + + width = 0.3 + for i in range(len(FIGURE_LABEL)): + bars[i] = ax1.bar(x_values, data, width, + hatch=PATTERNS[i], + color=LINE_COLORS[i], + label=FIGURE_LABEL[i], + edgecolor='black', linewidth=3) + + # LEGEND + + figlegend.legend(bars, FIGURE_LABEL, prop=LEGEND_FP, \ + loc=1, ncol=len(FIGURE_LABEL), mode="expand", shadow=True, \ + frameon=True, handlelength=2, handletextpad=0.3, columnspacing=0.5, + borderaxespad=-0.2, fancybox=True + ) + figlegend.savefig(FIGURE_FOLDER + '/' + filename + '.pdf') + + +# draw a bar chart +def DrawFigure(x_values, y_values, legend_labels, x_label, y_label, y_min, y_max, filename, allow_legend): + # you may change the figure size on your own. + fig = plt.figure(figsize=(10, 3)) + figure = fig.add_subplot(111) + + FIGURE_LABEL = legend_labels + + # values in the x_xis + index = np.arange(len(x_values)) + # the bar width. + # you may need to tune it to get the best figure. + width = 0.08 + # draw the bars + bars = [] + ts = 0 + pos = 0 + gl = len(y_values[0]) + for i in range(len(y_values)): + pos = pos + 3 * width + for j in range(len(y_values[i])): + pos = pos + width + bar = plt.bar(pos, y_values[i][j], width, hatch=PATTERNS[j], color=LINE_COLORS[j], label=FIGURE_LABEL[j], + edgecolor='black', linewidth=3) + bars.append(bar) + ts = ts + 1 + + # sometimes you may not want to draw legends. + if allow_legend == True: + plt.legend(bars, FIGURE_LABEL, + prop=LEGEND_FP, + ncol=4, + loc='upper center', + # mode='expand', + shadow=False, + bbox_to_anchor=(0.45, 1.6), + columnspacing=0.1, + handletextpad=0.2, + # bbox_transform=ax.transAxes, + # frameon=True, + # columnspacing=5.5, + # handlelength=2, + ) + + # you may need to tune the xticks position to get the best figure. + plt.xticks(index, x_values) + # plt.ticklabel_format(axis="y", style="sci", scilimits=(0, 0)) + # plt.grid(axis='y', color='gray') + # figure.get_xaxis().set_major_formatter(matplotlib.ticker.ScalarFormatter()) + + # you may need to tune the xticks position to get the best figure. + # plt.yscale('log') + # + # plt.grid(axis='y', color='gray') + figure.yaxis.set_major_locator(LinearLocator(5)) + # figure.xaxis.set_major_locator(LinearLocator(5)) + figure.get_xaxis().set_tick_params(direction='in', pad=10) + figure.get_yaxis().set_tick_params(direction='in', pad=10) + + plt.xlabel(x_label, fontproperties=LABEL_FP) + plt.ylabel(y_label, fontproperties=LABEL_FP) + plt.ylim(y_min, y_max) + plt.savefig(filename + ".pdf", bbox_inches='tight') + + +# example for reading csv file +def ReadFile(): + y = [] + col1 = [] + col2 = [] + col3 = [] + col4 = [] + col5 = [] + col6 = [] + col7 = [] + col8 = [] + col9 = [] + + for id in it.chain(range(38, 42)): + col9.append(0) + y.append(col9) # this is a lz4_pipe2 empty line to separate eager and lazy. + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/NPJ_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get the 99th timestamp + col1.append(x) + y.append(col1) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/PRJ_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get the 99th timestamp + col2.append(x) + y.append(col2) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/MWAY_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get the 99th timestamp + col3.append(x) + y.append(col3) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/MPASS_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get the 99th timestamp + col4.append(x) + y.append(col4) + + y.append(col9) # this is a lz4_pipe2 empty line to separate eager and lazy. + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/SHJ_JM_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get last timestamp + col5.append(x) + y.append(col5) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/SHJ_JBCR_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get last timestamp + col6.append(x) + y.append(col6) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/PMJ_JM_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get last timestamp + col7.append(x) + y.append(col7) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/PMJ_JBCR_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get last timestamp + col8.append(x) + y.append(col8) + return y + + +if __name__ == "__main__": + x_values = ["Stock", "Rovio", "YSB", "DEBS"] + + y_values = ReadFile() + + legend_labels = ['Lazy:', 'NPJ', 'PRJ', 'MWAY', 'MPASS', + 'Eager:', 'SHJ$^{JM}$', 'SHJ$^{JB}$', 'PMJ$^{JM}$', 'PMJ$^{JB}$'] + print(y_values) + DrawFigure(x_values, y_values, legend_labels, + '', 'Latency (ms)', 0, + 400, 'latency_figure_app', False) + + # DrawLegend(legend_labels, 'latency_legend') diff --git a/benchmark/scripts/scanAlgoBeta/groupBar2.py b/benchmark/scripts/scanAlgoBeta/groupBar2.py new file mode 100755 index 00000000..31155695 --- /dev/null +++ b/benchmark/scripts/scanAlgoBeta/groupBar2.py @@ -0,0 +1,232 @@ +import itertools as it +import os + +import matplotlib +import matplotlib.pyplot as plt +import numpy as np +import pylab +from matplotlib.font_manager import FontProperties +from matplotlib.ticker import LogLocator, LinearLocator + +OPT_FONT_NAME = 'Helvetica' +TICK_FONT_SIZE = 24 +LABEL_FONT_SIZE = 28 +LEGEND_FONT_SIZE = 30 +LABEL_FP = FontProperties(style='normal', size=LABEL_FONT_SIZE) +LEGEND_FP = FontProperties(style='normal', size=LEGEND_FONT_SIZE) +TICK_FP = FontProperties(style='normal', size=TICK_FONT_SIZE) + +MARKERS = (["", 'o', 's', 'v', "^", "", "h", "<", ">", "+", "d", "<", "|", "", "+", "_"]) +# you may want to change the color map for different figures +COLOR_MAP = ( + '#FFFFFF', '#B03A2E', '#2874A6', '#239B56', '#7D3C98', '#00FFFF', '#F1C40F', '#F5CBA7', '#82E0AA', '#AEB6BF', + '#AA4499') +# you may want to change the patterns for different figures +PATTERNS = ( + ["", "////", "\\\\", "//", "o", "", "||", "-", "//", "\\", "o", "O", "////", ".", "|||", "o", "---", "+", "\\\\", + "*"]) +LABEL_WEIGHT = 'bold' +LINE_COLORS = COLOR_MAP +LINE_WIDTH = 3.0 +MARKER_SIZE = 15.0 +MARKER_FREQUENCY = 1000 + +matplotlib.rcParams['ps.useafm'] = True +matplotlib.rcParams['pdf.use14corefonts'] = True +matplotlib.rcParams['xtick.labelsize'] = TICK_FONT_SIZE +matplotlib.rcParams['ytick.labelsize'] = TICK_FONT_SIZE +matplotlib.rcParams['font.family'] = OPT_FONT_NAME +matplotlib.rcParams['pdf.fonttype'] = 42 + +exp_dir = "/data1/xtra" + +FIGURE_FOLDER = exp_dir + '/results/figure' + + +def DrawLegend(legend_labels, filename): + fig = pylab.figure() + ax1 = fig.add_subplot(111) + FIGURE_LABEL = legend_labels + LEGEND_FP = FontProperties(style='normal', size=26) + figlegend = pylab.figure(figsize=(16, 0.5)) + bars = [None] * (len(FIGURE_LABEL)) + data = [1] + x_values = [1] + + width = 0.3 + for i in range(len(FIGURE_LABEL)): + bars[i] = ax1.bar(x_values, data, width, + hatch=PATTERNS[i], + color=LINE_COLORS[i], + label=FIGURE_LABEL[i], + edgecolor='black', linewidth=3) + + # LEGEND + + figlegend.legend(bars, FIGURE_LABEL, prop=LEGEND_FP, \ + loc=1, ncol=len(FIGURE_LABEL), mode="expand", shadow=True, \ + frameon=True, handlelength=2, handletextpad=0.3, columnspacing=0.5, + borderaxespad=-0.2, fancybox=True + ) + figlegend.savefig(FIGURE_FOLDER + '/' + filename + '.pdf') + + +# draw a bar chart +def DrawFigure(x_values, y_values, legend_labels, x_label, y_label, y_min, y_max, filename, allow_legend): + # you may change the figure size on your own. + fig = plt.figure(figsize=(10, 3)) + figure = fig.add_subplot(111) + + FIGURE_LABEL = legend_labels + + # values in the x_xis + index = np.arange(len(x_values)) + # the bar width. + # you may need to tune it to get the best figure. + width = 0.12 + # draw the bars + bars = [None] * (len(FIGURE_LABEL)) + for i in range(len(y_values)): + bars[i] = plt.bar(index + i * width + width / 2, + y_values[i], width, + hatch=PATTERNS[i], + color=LINE_COLORS[i], + label=FIGURE_LABEL[i], edgecolor='black', linewidth=3) + + # sometimes you may not want to draw legends. + if allow_legend == True: + plt.legend(bars, FIGURE_LABEL, + prop=LEGEND_FP, + ncol=3, + loc='upper center', + # mode='expand', + shadow=False, + bbox_to_anchor=(0.45, 1.7), + columnspacing=0.1, + handletextpad=0.2, + # bbox_transform=ax.transAxes, + # frameon=True, + # columnspacing=5.5, + # handlelength=2, + ) + + # you may need to tune the xticks position to get the best figure. + plt.xticks(index + 3 * width, x_values, rotation=30) + + # plt.ticklabel_format(axis="y", style="sci", scilimits=(0, 0)) + # plt.grid(axis='y', color='gray') + # figure.get_xaxis().set_major_formatter(matplotlib.ticker.ScalarFormatter()) + + # you may need to tune the xticks position to get the best figure. + # plt.yscale('log') + # + # plt.grid(axis='y', color='gray') + figure.yaxis.set_major_locator(LinearLocator(10)) + # figure.xaxis.set_major_locator(LinearLocator(5)) + figure.get_xaxis().set_tick_params(direction='in', pad=10) + figure.get_yaxis().set_tick_params(direction='in', pad=10) + + plt.xlabel(x_label, fontproperties=LABEL_FP) + plt.ylabel(y_label, fontproperties=LABEL_FP) + + plt.savefig(filename + ".pdf", bbox_inches='tight') + + +# example for reading csv file +def ReadFile(): + y = [] + col1 = [] + col2 = [] + col3 = [] + col4 = [] + col5 = [] + col6 = [] + col7 = [] + col8 = [] + col9 = [] + + for id in it.chain(range(38, 42)): + col9.append(0) + y.append(col9) # this is a fake empty line to separate eager and lazy. + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/NPJ_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get the 99th timestamp + col1.append(x) + y.append(col1) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/PRJ_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get the 99th timestamp + col2.append(x) + y.append(col2) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/MWAY_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get the 99th timestamp + col3.append(x) + y.append(col3) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/MPASS_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get the 99th timestamp + col4.append(x) + y.append(col4) + + y.append(col9) # this is a fake empty line to separate eager and lazy. + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/SHJ_JM_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get last timestamp + col5.append(x) + y.append(col5) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/SHJ_JBCR_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get last timestamp + col6.append(x) + y.append(col6) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/PMJ_JM_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get last timestamp + col7.append(x) + y.append(col7) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/PMJ_JBCR_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get last timestamp + col8.append(x) + y.append(col8) + return y + + +if __name__ == "__main__": + x_values = ["Stock", "Rovio", "YSB", "DEBS"] + + y_values = ReadFile() + + legend_labels = ['Lazy:', 'NPJ', 'PRJ', 'MWAY', 'MPASS', + 'Eager:', 'SHJ$^{JM}$', 'SHJ$^{JB}$', 'PMJ$^{JM}$', 'PMJ$^{JB}$'] + print(y_values) + DrawFigure(x_values, y_values, legend_labels, + '', 'Latency (ms)', 0, + 400, 'latency_figure_app', False) + + # DrawLegend(legend_labels, 'latency_legend') diff --git a/benchmark/scripts/scanAlgoBeta/groupLine.py b/benchmark/scripts/scanAlgoBeta/groupLine.py new file mode 100755 index 00000000..8110fd3b --- /dev/null +++ b/benchmark/scripts/scanAlgoBeta/groupLine.py @@ -0,0 +1,366 @@ +import itertools as it +import os +import matplotlib.pyplot as plt +import matplotlib.font_manager as fm +import matplotlib +import numpy as np +import pylab +from matplotlib.font_manager import FontProperties +from matplotlib.ticker import MaxNLocator +from matplotlib.font_manager import FontProperties +from matplotlib.ticker import LinearLocator, LogLocator, MaxNLocator, ScalarFormatter +from numpy import double + +# 获取系统中可用的字体路径 +# font_paths = fm.findSystemFonts() +# OPT_FONT_NAME = 'Helvetica' +TICK_FONT_SIZE = 20 +LABEL_FONT_SIZE = 20 +LEGEND_FONT_SIZE = 20 +LABEL_FP = FontProperties(style='normal', size=LABEL_FONT_SIZE) +LEGEND_FP = FontProperties(style='normal', size=LEGEND_FONT_SIZE) +TICK_FP = FontProperties(style='normal', size=TICK_FONT_SIZE) + +MARKERS = (['o', 's', 'v', "^", "h", "v", ">", "x", "d", "<", "|", "p", "+", "_", "%", "|", "|", "|", "|", "|"]) +# you may want to change the color map for different figures +COLOR_MAP = ( + '#F15854', '#5DA5DA', '#60BD68', '#B276B2', '#DECF3F', '#F17CB0', '#B2912F', '#FAA43A', '#AFAFAF', '#087878', + '#783456', + '#560012', '#431256', "#00AABB", "#AA00BB") +# you may want to change the patterns for different figures +PATTERNS = (["|", "\\", "/", "+", "-", ".", "*", "x", "o", "O", "////", ".", "|||", "o", "---", "+", "\\\\", "*"]) +LABEL_WEIGHT = 'bold' +LINE_COLORS = COLOR_MAP +LINE_WIDTH = 3.0 +MARKER_SIZE = 13.0 +MARKER_FREQUENCY = 1000 + +# matplotlib.rcParams['ps.useafm'] = True +# matplotlib.rcParams['pdf.use14corefonts'] = True +# matplotlib.rcParams['xtick.labelsize'] = TICK_FONT_SIZE +# matplotlib.rcParams['ytick.labelsize'] = TICK_FONT_SIZE +# 创建字体列表 +# Explicitly specify the font path +# 获取系统中可用的字体路径 +font_paths = fm.findSystemFonts() + +# 创建字体列表 +font_list = [] +for font_path in font_paths: + try: + font_name = fm.FontProperties(fname=font_path).get_name() + if font_name not in font_list: + font_list.append(font_name) + except: + pass + +# 配置 matplotlib 使用系统中可用的字体 +plt.rcParams['font.family'] = font_list[0] + +FIGURE_FOLDER = '/data1/xtra/results/figure' + + +# there are some embedding problems if directly exporting the pdf figure using matplotlib. +# so we generate the eps format first and convert it to pdf. +def ConvertEpsToPdf(dir_filename): + os.system("epstopdf --outfile " + dir_filename + ".pdf " + dir_filename + ".eps") + os.system("rm -rf " + dir_filename + ".eps") + + +def DrawLegend(legend_labels, filename): + fig = pylab.figure() + ax1 = fig.add_subplot(111) + FIGURE_LABEL = legend_labels + LINE_WIDTH = 8.0 + MARKER_SIZE = 12.0 + LEGEND_FP = FontProperties(style='normal', size=26) + + figlegend = pylab.figure(figsize=(12, 0.5)) + idx = 0 + lines = [None] * (len(FIGURE_LABEL)) + data = [1] + x_values = [1] + + idx = 0 + for group in range(len(FIGURE_LABEL)): + lines[idx], = ax1.plot(x_values, data, + color=LINE_COLORS[idx], linewidth=LINE_WIDTH, + marker=MARKERS[idx], markersize=MARKER_SIZE, label=str(group)) + idx = idx + 1 + + # LEGEND + figlegend.legend(lines, FIGURE_LABEL, prop=LEGEND_FP, + loc=1, ncol=len(FIGURE_LABEL), mode="expand", shadow=False, + frameon=False, borderaxespad=0.0, handlelength=2) + + if not os.path.exists(FIGURE_FOLDER): + os.makedirs(FIGURE_FOLDER) + # no need to export eps in this case. + figlegend.savefig(filename + '.pdf') + + +# draw a line chart +def DrawFigure(xvalues, yvalues, legend_labels, x_label, y_label, y_min, y_max, filename, allow_legend): + # you may change the figure size on your own. + fig = plt.figure(figsize=(10, 3)) + figure = fig.add_subplot(111) + + FIGURE_LABEL = legend_labels + + x_values = xvalues + y_values = yvalues + + lines = [None] * (len(FIGURE_LABEL)) + for i in range(len(y_values)): + lines[i], = figure.plot(x_values[i], y_values[i], color=LINE_COLORS[i], \ + linewidth=LINE_WIDTH, marker=MARKERS[i], \ + markersize=MARKER_SIZE, label=FIGURE_LABEL[i]) + + # sometimes you may not want to draw legends. + if allow_legend == True: + plt.legend(lines, + FIGURE_LABEL, + prop=LEGEND_FP, + loc='upper center', + ncol=3, + # mode='expand', + bbox_to_anchor=(0.55, 1.6), shadow=False, + columnspacing=0.1, + frameon=True, borderaxespad=0.0, handlelength=1.5, + handletextpad=0.1, + labelspacing=0.1) + plt.xscale('log') + plt.yscale('log') + # plt.yscale('log') + + # you may control the limits on your own. + + # plt.ylim(y_min, y_max) + + plt.grid(axis='y', color='gray') + figure.yaxis.set_major_locator(LogLocator(base=10)) + figure.xaxis.set_major_locator(LogLocator(base=10)) + + figure.get_xaxis().set_tick_params(direction='in', pad=10) + figure.get_yaxis().set_tick_params(direction='in', pad=10) + + plt.xlabel(x_label, fontproperties=LABEL_FP) + plt.ylabel(y_label, fontproperties=LABEL_FP) + + size = fig.get_size_inches() + dpi = fig.get_dpi() + + # plt.show() + plt.savefig(filename + ".pdf", bbox_inches='tight') + + +# draw a line chart +def DrawFigureXYnormal(xvalues, yvalues, legend_labels, x_label, y_label, y_min, y_max, filename, allow_legend): + # you may change the figure size on your own. + fig = plt.figure(figsize=(10, 3)) + figure = fig.add_subplot(111) + + FIGURE_LABEL = legend_labels + + x_values = xvalues + y_values = yvalues + + lines = [None] * (len(FIGURE_LABEL)) + for i in range(len(y_values)): + lines[i], = figure.plot(x_values[i], y_values[i], color=LINE_COLORS[i], \ + linewidth=LINE_WIDTH, marker=MARKERS[i], \ + markersize=MARKER_SIZE, label=FIGURE_LABEL[i], markeredgecolor='k') + + # sometimes you may not want to draw legends. + if allow_legend == True: + plt.legend(lines, + FIGURE_LABEL, + prop=LEGEND_FP, + loc='upper center', + ncol=3, + bbox_to_anchor=(0.55, 1.5), shadow=False, + columnspacing=0.1, + frameon=True, borderaxespad=0, handlelength=1.2, + handletextpad=0.1, + labelspacing=0.1) + # plt.xscale('log') + # plt.yscale('log') + # plt.yscale('log') + + # you may control the limits on your own. + + # plt.ylim(y_min, y_max) + + plt.grid(axis='y', color='gray') + plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号 + # figure.yaxis.set_major_locator(LogLocator(base=10)) + # figure.xaxis.set_major_locator(LogLocator(base=10)) + plt.xticks(rotation=0, fontsize=TICK_FONT_SIZE) + figure.get_xaxis().set_tick_params(direction='in', pad=10) + figure.get_yaxis().set_tick_params(direction='in', pad=10) + + plt.xlabel(x_label, fontproperties=LABEL_FP) + plt.ylabel(y_label, fontproperties=LABEL_FP) + + size = fig.get_size_inches() + dpi = fig.get_dpi() + + # plt.show() + plt.savefig(filename + ".pdf", bbox_inches='tight') + + +# draw a line chart +def DrawFigureYnormal(xvalues, yvalues, legend_labels, x_label, y_label, y_min, y_max, filename, allow_legend): + # you may change the figure size on your own. + fig = plt.figure(figsize=(10, 3)) + figure = fig.add_subplot(111) + + FIGURE_LABEL = legend_labels + + x_values = xvalues + y_values = yvalues + + lines = [None] * (len(FIGURE_LABEL)) + for i in range(len(y_values)): + lines[i], = figure.plot(x_values[i], y_values[i], color=LINE_COLORS[i], \ + linewidth=LINE_WIDTH, marker=MARKERS[i], \ + markersize=MARKER_SIZE, label=FIGURE_LABEL[i], markeredgecolor='k') + + # sometimes you may not want to draw legends. + if allow_legend == True: + plt.legend(lines, + FIGURE_LABEL, + prop=LEGEND_FP, + loc='upper center', + ncol=3, + bbox_to_anchor=(0.55, 1.5), shadow=False, + columnspacing=0.1, + frameon=True, borderaxespad=0, handlelength=1.2, + handletextpad=0.1, + labelspacing=0.1) + plt.xscale('log') + # plt.yscale('log') + # plt.yscale('log') + + # you may control the limits on your own. + + # plt.ylim(y_min, y_max) + + plt.grid(axis='y', color='gray') + plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号 + # figure.yaxis.set_major_locator(LogLocator(base=10)) + # figure.xaxis.set_major_locator(LogLocator(base=10)) + plt.xticks(rotation=0, fontsize=TICK_FONT_SIZE) + figure.get_xaxis().set_tick_params(direction='in', pad=10) + figure.get_yaxis().set_tick_params(direction='in', pad=10) + + plt.xlabel(x_label, fontproperties=LABEL_FP) + plt.ylabel(y_label, fontproperties=LABEL_FP) + + size = fig.get_size_inches() + dpi = fig.get_dpi() + + # plt.show() + plt.savefig(filename + ".pdf", bbox_inches='tight') + + +# example for reading csv file +def ReadFile(): + y = [] + col1 = [] + col2 = [] + col3 = [] + col4 = [] + col5 = [] + col6 = [] + col7 = [] + col8 = [] + + for id in it.chain(range(28, 32)): + file = '/data1/xtra/results/timestamps/PRJ_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(len(read) - 1).strip("\n")) # get last timestamp + value = len(read) / x # get throughput (#items/ms) + col1.append(value) + y.append(col1) + + for id in it.chain(range(28, 32)): + file = '/data1/xtra/results/timestamps/NPJ_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(len(read) - 1).strip("\n")) # get last timestamp + value = len(read) / x # get throughput (#items/ms) + col2.append(value) + y.append(col2) + + for id in it.chain(range(28, 32)): + file = '/data1/xtra/results/timestamps/MPASS_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(len(read) - 1).strip("\n")) # get last timestamp + value = len(read) / x # get throughput (#items/ms) + col3.append(value) + y.append(col3) + + for id in it.chain(range(28, 32)): + file = '/data1/xtra/results/timestamps/MWAY_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(len(read) - 1).strip("\n")) # get last timestamp + value = len(read) / x # get throughput (#items/ms) + col4.append(value) + y.append(col4) + + for id in it.chain(range(28, 32)): + file = '/data1/xtra/results/timestamps/SHJ_JM_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(len(read) - 1).strip("\n")) # get last timestamp + value = len(read) / x # get throughput (#items/ms) + col5.append(value) + y.append(col5) + + for id in it.chain(range(28, 32)): + file = '/data1/xtra/results/timestamps/SHJ_JBCR_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(len(read) - 1).strip("\n")) # get last timestamp + value = len(read) / x # get throughput (#items/ms) + col6.append(value) + y.append(col6) + + for id in it.chain(range(28, 32)): + file = '/data1/xtra/results/timestamps/PMJ_JM_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(len(read) - 1).strip("\n")) # get last timestamp + value = len(read) / x # get throughput (#items/ms) + col7.append(value) + y.append(col7) + + for id in it.chain(range(28, 32)): + file = '/data1/xtra/results/timestamps/PMJ_JBCR_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(len(read) - 1).strip("\n")) # get last timestamp + value = len(read) / x # get throughput (#items/ms) + col8.append(value) + y.append(col8) + return y + + +if __name__ == "__main__": + # x_values = ['Unique', 'Zipf(0)', 'Zipf(0.2)', 'Zipf(0.4)', 'Zipf(0.8)', 'Zipf(1)'] + x_values = [1600, 3200, 6400, 12800, 25600] + + y_values = ReadFile() + + legend_labels = ['NPJ', 'PRJ', 'MWAY', 'MPASS', 'SHJ$^{JM}$', 'SHJ$^{JB}$', 'PMJ$^{JM}$', + 'PMJ$^{JB}$'] + + DrawFigure(x_values, y_values, legend_labels, + 'Input arrival rate of R (e/ms)', 'Tpt. (#matches/ms)', x_values[0], + x_values[4], 'throughput_figure1_1', False) + +# DrawLegend(legend_labels, 'factor_legend') diff --git a/benchmark/scripts/scanAlgoBeta/perfRu.csv b/benchmark/scripts/scanAlgoBeta/perfRu.csv new file mode 100644 index 00000000..9ee43623 --- /dev/null +++ b/benchmark/scripts/scanAlgoBeta/perfRu.csv @@ -0,0 +1,7 @@ +key,value,type +cacheMiss,12491377,U64 +cacheRefs,35327177,U64 +cpuClock,2478812100,U64 +cpuCycle,9889422467,U64 +instructions,16997458033,U64 +taskClock,2478813000,U64 diff --git a/benchmark/scripts/scanAlgoDelta/OoOCommon.py b/benchmark/scripts/scanAlgoDelta/OoOCommon.py new file mode 100755 index 00000000..70f4cf33 --- /dev/null +++ b/benchmark/scripts/scanAlgoDelta/OoOCommon.py @@ -0,0 +1,125 @@ +import csv +import numpy as np +import matplotlib.pyplot as plt +import itertools as it +import os + +import matplotlib +import matplotlib.pyplot as plt +import numpy as np +import pylab +from matplotlib.font_manager import FontProperties +from matplotlib.ticker import LogLocator, LinearLocator +import os +import pandas as pd +import sys +import matplotlib.ticker as mtick + +OPT_FONT_NAME = 'Helvetica' +TICK_FONT_SIZE = 22 +LABEL_FONT_SIZE = 28 +LEGEND_FONT_SIZE = 30 +LABEL_FP = FontProperties(style='normal', size=LABEL_FONT_SIZE) +LEGEND_FP = FontProperties(style='normal', size=LEGEND_FONT_SIZE) +TICK_FP = FontProperties(style='normal', size=TICK_FONT_SIZE) + +MARKERS = (['*', '|', 'v', "^", "", "h", "<", ">", "+", "d", "<", "|", "", "+", "_"]) +# you may want to change the color map for different figures +COLOR_MAP = ( + '#B03A2E', '#2874A6', '#239B56', '#7D3C98', '#FFFFFF', '#F1C40F', '#F5CBA7', '#82E0AA', '#AEB6BF', '#AA4499') +# you may want to change the patterns for different figures +PATTERNS = (["////", "o", "", "||", "-", "//", "\\", "o", "O", "////", ".", "|||", "o", "---", "+", "\\\\", "*"]) +LABEL_WEIGHT = 'bold' +LINE_COLORS = COLOR_MAP +LINE_WIDTH = 3.0 +MARKER_SIZE = 15.0 +MARKER_FREQUENCY = 1000 + + +def editConfig(src, dest, key, value): + df = pd.read_csv(src, header=None) + rowIdx = 0 + idxt = 0 + for cell in df[0]: + # print(cell) + if (cell == key): + rowIdx = idxt + break + idxt = idxt + 1 + df[1][rowIdx] = str(value) + df.to_csv(dest, index=False, header=False) + + +def readConfig(src, key): + df = pd.read_csv(src, header=None) + rowIdx = 0 + idxt = 0 + for cell in df[0]: + # print(cell) + if (cell == key): + rowIdx = idxt + break + idxt = idxt + 1 + return df[1][rowIdx] + + +def draw2yLine(NAME, Com, R1, R2, l1, l2, m1, m2, fname): + fig, ax1 = plt.subplots(figsize=(10, 6.4)) + lines = [None] * 2 + # ax1.set_ylim(0, 1) + print(Com) + print(R1) + lines[0], = ax1.plot(Com, R1, color=LINE_COLORS[0], \ + linewidth=LINE_WIDTH, marker=MARKERS[0], \ + markersize=MARKER_SIZE + # + ) + + # plt.show() + ax1.set_ylabel(m1, fontproperties=LABEL_FP) + ax1.set_xlabel(NAME, fontproperties=LABEL_FP) + # ax1.set_xticklabels(ax1.get_xticklabels()) # 设置共用的x轴 + plt.xticks(rotation=0, size=TICK_FONT_SIZE) + plt.yticks(rotation=0, size=TICK_FONT_SIZE) + plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号 + ax2 = ax1.twinx() + + # ax2.set_ylabel('latency/us') + # ax2.set_ylim(0, 0.5) + lines[1], = ax2.plot(Com, R2, color=LINE_COLORS[1], \ + linewidth=LINE_WIDTH, marker=MARKERS[1], \ + markersize=MARKER_SIZE) + + ax2.set_ylabel(m2, fontproperties=LABEL_FP) + # ax2.vlines(192000, min(R2)-1, max(R2)+1, colors = "GREEN", linestyles = "dashed",label='total L1 size') + # plt.grid(axis='y', color='gray') + + # style = dict(size=10, color='black') + # ax2.hlines(tset, 0, x2_list[len(x2_list)-1]+width, colors = "r", linestyles = "dashed",label="tset") + # ax2.text(4, tset, "$T_{set}$="+str(tset)+"us", ha='right', **style) + + # plt.xlabel('batch', fontproperties=LABEL_FP) + + # plt.xscale('log') + # figure.xaxis.set_major_locator(LinearLocator(5)) + ax1.yaxis.set_major_locator(LinearLocator(5)) + ax2.yaxis.set_major_locator(LinearLocator(5)) + ax1.yaxis.set_major_formatter(mtick.FormatStrFormatter('%.1f')) + ax2.yaxis.set_major_formatter(mtick.FormatStrFormatter('%.1f')) + ax1.yaxis.set_major_formatter(mtick.FormatStrFormatter('%.1f')) + ax2.yaxis.set_major_formatter(mtick.FormatStrFormatter('%.1f')) + plt.legend(lines, + [l1, l2], + prop=LEGEND_FP, + loc='upper center', + ncol=1, + bbox_to_anchor=(0.55, 1.3 + ), shadow=False, + columnspacing=0.1, + frameon=True, borderaxespad=-1.5, handlelength=1.2, + handletextpad=0.1, + labelspacing=0.1) + plt.yticks(rotation=0, size=TICK_FONT_SIZE) + plt.tight_layout() + + plt.savefig(fname + ".pdf") diff --git a/benchmark/scripts/scanAlgoDelta/accuBar.py b/benchmark/scripts/scanAlgoDelta/accuBar.py new file mode 100755 index 00000000..638c8a60 --- /dev/null +++ b/benchmark/scripts/scanAlgoDelta/accuBar.py @@ -0,0 +1,328 @@ +import getopt +import os +import sys + +import matplotlib +import matplotlib.pyplot as plt +import numpy as np +import pylab +from matplotlib.font_manager import FontProperties +from matplotlib.ticker import LinearLocator, LogLocator, MaxNLocator, ScalarFormatter +from numpy import double + +OPT_FONT_NAME = 'Helvetica' +TICK_FONT_SIZE = 24 +LABEL_FONT_SIZE = 28 +LEGEND_FONT_SIZE = 26 +TITLE_FRONT_SIZE = 32 +LABEL_FP = FontProperties(style='normal', size=LABEL_FONT_SIZE) +LEGEND_FP = FontProperties(style='normal', size=LEGEND_FONT_SIZE) +TICK_FP = FontProperties(style='normal', size=TICK_FONT_SIZE) +TITLE_FP = FontProperties(style='normal', size=TITLE_FRONT_SIZE) +MARKERS = (['o', 's', 'v', "^", "h", "v", ">", "x", "d", "<", "|", "", "|", "_"]) +# you may want to change the color map for different figures +COLOR_MAP = ('#B03A2E', '#2874A6', '#239B56', '#7D3C98', '#F1C40F', '#F5CBA7', '#82E0AA', '#AEB6BF', '#AA4499') +# you may want to change the patterns for different figures +PATTERNS = (["\\", "///", "o", "||", "\\\\", "\\\\", "//////", "//////", ".", "\\\\\\", "\\\\\\"]) +LABEL_WEIGHT = 'bold' +LINE_COLORS = COLOR_MAP +LINE_WIDTH = 3.0 +MARKER_SIZE = 0.0 +MARKER_FREQUENCY = 1000 + +matplotlib.rcParams['ps.useafm'] = True +matplotlib.rcParams['pdf.use14corefonts'] = True +matplotlib.rcParams['xtick.labelsize'] = TICK_FONT_SIZE +matplotlib.rcParams['ytick.labelsize'] = TICK_FONT_SIZE +matplotlib.rcParams['font.family'] = OPT_FONT_NAME +matplotlib.rcParams['pdf.fonttype'] = 42 + +exp_dir = "/data1/xtra" + +FIGURE_FOLDER = exp_dir + '/results/figure' + + +# there are some embedding problems if directly exporting the pdf figure using matplotlib. +# so we generate the eps format first and convert it to pdf. +def ConvertEpsToPdf(dir_filename): + os.system("epstopdf --outfile " + dir_filename + ".pdf " + dir_filename + ".eps") + os.system("rm -rf " + dir_filename + ".eps") + + +class ScalarFormatterForceFormat(ScalarFormatter): + def _set_format(self): # Override function that finds format to use. + self.format = "%1.1f" # Give format here + + +# draw a line chart +def DrawFigure(x_values, y_values, legend_labels, x_label, y_label, filename, allow_legend, title): + # you may change the figure size on your own. + + fig = plt.figure(figsize=(16, 9)) + figure = fig.add_subplot(111) + + FIGURE_LABEL = legend_labels + + # if not os.path.exists(FIGURE_FOLDER): + # os.makedirs(FIGURE_FOLDER) + + # values in the x_xis + index = np.arange(len(x_values)) + # the bar width. + # you may need to tune it to get the best figure. + width = 0.5 + # draw the bars + bottom_base = np.zeros(len(y_values[0])) + bars = [None] * (len(FIGURE_LABEL)) + for i in range(len(y_values)): + bars[i] = plt.bar(index + width / 2, y_values[i], width, hatch=PATTERNS[i], color=LINE_COLORS[i], + label=FIGURE_LABEL[i], bottom=bottom_base, edgecolor='black', linewidth=3) + bottom_base = np.array(y_values[i]) + bottom_base + + # sometimes you may not want to draw legends. + if allow_legend == True: + plt.legend(bars, FIGURE_LABEL + # mode='expand', + # shadow=False, + # columnspacing=0.25, + # labelspacing=-2.2, + # borderpad=5, + # bbox_transform=ax.transAxes, + # frameon=False, + # columnspacing=5.5, + # handlelength=2, + ) + if allow_legend == True: + handles, labels = figure.get_legend_handles_labels() + if allow_legend == True: + leg = plt.legend(handles[::-1], labels[::-1], + loc='upper center', + # prop=#LEGEND_FP, + # ncol=3, + # bbox_to_anchor=(0.5, 1.25), + # bbox_to_anchor=(1.17, 0.5), + # handletextpad=0.1, + # borderaxespad=0.0, + # handlelength=1.8, + # labelspacing=0.3, + # columnspacing=0.3, + ) + leg.get_frame().set_linewidth(2) + leg.get_frame().set_edgecolor("black") + + # you may need to tune the xticks position to get the best figure. + plt.xticks(index + 0.6 * width, x_values) + yfmt = ScalarFormatterForceFormat() + yfmt.set_powerlimits((0, 0)) + figure.get_yaxis().set_major_formatter(yfmt) + plt.ticklabel_format(axis="y", style="sci", scilimits=(0, 0), useMathText=True) + plt.grid(axis='y', color='gray') + figure.yaxis.set_major_locator(LinearLocator(3)) + # figure.yaxis.set_major_locator(LogLocator(base=10)) + # figure.yaxis.set_major_locator(LinearLocator(6)) + + figure.get_xaxis().set_tick_params(direction='in', pad=10) + figure.get_yaxis().set_tick_params(direction='in', pad=10) + + plt.xlabel(x_label, fontproperties=LABEL_FP) + plt.ylabel(y_label, fontproperties=LABEL_FP) + + size = fig.get_size_inches() + dpi = fig.get_dpi() + plt.title(title, fontproperties=TITLE_FP) + plt.savefig(filename + ".pdf", bbox_inches='tight', format='pdf') + + +def DrawLegend(legend_labels, filename): + fig = pylab.figure() + ax1 = fig.add_subplot(111) + FIGURE_LABEL = legend_labels + LEGEND_FP = FontProperties(style='normal', size=26) + + bars = [None] * (len(FIGURE_LABEL)) + data = [1] + x_values = [1] + + width = 0.3 + for i in range(len(FIGURE_LABEL)): + bars[i] = ax1.bar(x_values, data, width, hatch=PATTERNS[i], color=LINE_COLORS[i], + linewidth=0.2) + + # LEGEND + figlegend = pylab.figure(figsize=(11, 0.5)) + figlegend.legend(bars, FIGURE_LABEL, prop=LEGEND_FP, \ + loc=9, + bbox_to_anchor=(0, 0.4, 1, 1), + ncol=len(FIGURE_LABEL), mode="expand", shadow=False, \ + frameon=False, handlelength=1.1, handletextpad=0.2, columnspacing=0.1) + + figlegend.savefig(FIGURE_FOLDER + '/' + filename + '.pdf') + + +def normalize(y_values): + y_total_values = np.zeros(len(y_values[0])) + + for i in range(len(y_values)): + y_total_values += np.array(y_values[i]) + y_norm_values = [] + + for i in range(len(y_values)): + y_norm_values.append(np.array(y_values[i]) / (y_total_values) * 100) + return y_norm_values + + +# example for reading csv file +def ReadFile(id): + # Creates a list containing w lists, each of h items, all set to 0 + w, h = 5, 3 + y = [[0 for x in range(w)] for y in range(h)] + # print(matches) + max_value = 0 + j = 0 + bound = id + 1 * w + for i in range(id, bound, 1): + cnt = 0 + print(i) + f = open(exp_dir + "/results/breakdown/PMJ_JBCR_NP_{}.txt".format(i), "r") + read = f.readlines() + others = 0 + for x in read: + value = double(x.strip("\n")) + if value > max_value: + max_value = value + elif cnt == 3: # sort + y[0][j] = value + elif cnt == 4: # merge + y[1][j] = value + elif cnt == 5: # join + y[2][j] = value + else: + others += value + # if cnt == 6: + # y[2][j] = others + cnt += 1 + j += 1 + print(y) + return y, max_value + + +if __name__ == "__main__": + id = 119 + try: + opts, args = getopt.getopt(sys.argv[1:], '-i:h', ['test id', 'help']) + except getopt.GetoptError: + print('breakdown.py -id testid') + sys.exit(2) + for opt, opt_value in opts: + if opt in ('-h', '--help'): + print("[*] Help info") + exit() + elif opt == '-i': + print('Test ID:', opt_value) + id = (int)(opt_value) + + x_values = ['10%', '20%', '30%', '40%', '50%'] # sorting step size + + y_values, max_value = ReadFile(id) # 55 + + # y_norm_values = normalize(y_values) + + # break into 4 parts + legend_labels = ['sort', 'merge', 'join'] # , 'others' + + DrawFigure(x_values, y_values, legend_labels, + 'sorting step size', 'cycles per input tuple', + 'breakdown_sort_figure', True) + + # DrawLegend(legend_labels, 'breakdown_radix_legend') + + +def DrawPercentageFigure(x_values, y_values, legend_labels, x_label, y_label, filename, allow_legend, title): + # you may change the figure size on your own. + fig = plt.figure(figsize=(9, 3)) + figure = fig.add_subplot(111) + + FIGURE_LABEL = legend_labels + + # values in the x_xis + index = np.arange(len(x_values)) + # the bar width. + # you may need to tune it to get the best figure. + width = 0.5 + # draw the bars + bottom_base = np.zeros(len(y_values[0])) + bars = [None] * (len(FIGURE_LABEL)) + for i in range(len(y_values)): + bars[i] = plt.bar(index + width / 2, y_values[i], width, hatch=PATTERNS[i], color=LINE_COLORS[i], + label=FIGURE_LABEL[i], bottom=bottom_base, edgecolor='black', linewidth=3) + bottom_base = np.array(y_values[i]) + bottom_base + + # sometimes you may not want to draw legends. + if allow_legend == True: + plt.legend(bars, FIGURE_LABEL + # mode='expand', + # shadow=False, + # columnspacing=0.25, + # labelspacing=-2.2, + # borderpad=5, + # bbox_transform=ax.transAxes, + # frameon=False, + # columnspacing=5.5, + # handlelength=2, + ) + if allow_legend == True: + handles, labels = figure.get_legend_handles_labels() + if allow_legend == True: + print(handles[::-1], labels[::-1]) + leg = plt.legend(handles[::-1], labels[::-1], + loc='center', + prop=LEGEND_FP, + ncol=3, + bbox_to_anchor=(0.5, 1.2), + handletextpad=0.1, + borderaxespad=0.0, + handlelength=1.8, + labelspacing=0.3, + columnspacing=0.3, + ) + leg.get_frame().set_linewidth(2) + leg.get_frame().set_edgecolor("black") + + # sometimes you may not want to draw legends. + # if allow_legend == True: + # leg=plt.legend(bars, + # FIGURE_LABEL, + # prop=LEGEND_FP, + # loc='right', + # ncol=1, + # # mode='expand', + # bbox_to_anchor=(0.45, 1.1), shadow=False, + # columnspacing=0.1, + # frameon=True, borderaxespad=0.0, handlelength=1.5, + # handletextpad=0.1, + # labelspacing=0.1) + # leg.get_frame().set_linewidth(2) + # leg.get_frame().set_edgecolor("black") + + plt.ylim(0, 100) + + # you may need to tune the xticks position to get the best figure. + plt.xticks(index + 0.5 * width, x_values) + plt.xticks(rotation=30) + + # plt.xlim(0,) + # plt.ylim(0,1) + + plt.grid(axis='y', color='gray') + figure.yaxis.set_major_locator(LinearLocator(6)) + + figure.get_xaxis().set_tick_params(direction='in', pad=10) + figure.get_yaxis().set_tick_params(direction='in', pad=10) + + plt.xlabel(x_label, fontproperties=LABEL_FP) + plt.ylabel(y_label, fontproperties=LABEL_FP) + + size = fig.get_size_inches() + dpi = fig.get_dpi() + + plt.savefig(filename + ".pdf", bbox_inches='tight', format='pdf') diff --git a/benchmark/scripts/scanAlgoDelta/autoParase.py b/benchmark/scripts/scanAlgoDelta/autoParase.py new file mode 100755 index 00000000..9375c8e0 --- /dev/null +++ b/benchmark/scripts/scanAlgoDelta/autoParase.py @@ -0,0 +1,87 @@ +import csv + + +def paraseValidStageNames(a): + nameList = [] + with open(a, 'r') as f: + reader = csv.reader(f) + # reader = [each for each in csv.DictReader(f, delimiter=',')] + result = list(reader) + rows = len(result) + # print('rows=',rows) + firstRow = result[0] + # print(firstRow) + index = 0 + # define what may attract our interest + idxCpu = 0 + idxName = 0 + for i in firstRow: + # print(i) + if (i == 'cpu'): + idxCpu = index + if (i == 'name'): + idxName = index + index = index + 1 + # read the valid stages + vdataEntries = 0 + + for k in range(1, rows): + if (result[k][idxCpu] != 'NA'): + R1 = ((result[k][idxName])) + nameList.append(R1) + return nameList + + +def paraseValidColums(a, nameList, colTitle): + with open(a, 'r') as f: + reader = csv.reader(f) + # reader = [each for each in csv.DictReader(f, delimiter=',')] + result = list(reader) + rows = len(result) + # print('rows=',rows) + firstRow = result[0] + # print(firstRow) + index = 0 + # define what may attract our interest + idxCpu = 0 + idxName = 0 + idxTitle = 0 + for i in firstRow: + # print(i) + if (i == 'cpu'): + idxCpu = index + if (i == 'name'): + idxName = index + if (i == colTitle): + idxTitle = index + index = index + 1 + # read the valid stages + vdataEntries = 0 + ru = [] + for k in range(1, rows): + if (result[k][idxCpu] != 'NA'): + R1 = ((result[k][idxName])) + for j in range(len(nameList)): + if (R1 == nameList[j]): + s = int(result[k][idxTitle]) + ru.append(s) + break + return ru + + +def maxInList(a): + # a in [[1,2] [3,4]] + inLen = len(a[0]) + ru = [] + index = [] + ti = 0 + for i in range(len(a[0])): + ts = 0 + ti = 0 + for k in range(len(a)): + if (a[k][i] > ts): + ts = a[k][i] + ti = k + ru.append(ts) + index.append(ti) + return ru, index diff --git a/benchmark/scripts/scanAlgoDelta/config_CPPTOW.csv b/benchmark/scripts/scanAlgoDelta/config_CPPTOW.csv new file mode 100644 index 00000000..5bd39217 --- /dev/null +++ b/benchmark/scripts/scanAlgoDelta/config_CPPTOW.csv @@ -0,0 +1,11 @@ +key,value,type +aRow,100,U64 +aCol,1000,U64 +bCol,500,U64 +sketchDimension,25,U64 +ptFile,torchscripts/TugOfWar.pt,String +useCPP,1,U64 +cppAlgoTag,tugOfWar,String +threads,1,U64 +forceMP,1,U64 +algoDelta,0.02,Double diff --git a/benchmark/scripts/scanAlgoDelta/config_RAWMM.csv b/benchmark/scripts/scanAlgoDelta/config_RAWMM.csv new file mode 100644 index 00000000..a1e0fe71 --- /dev/null +++ b/benchmark/scripts/scanAlgoDelta/config_RAWMM.csv @@ -0,0 +1,9 @@ +key,value,type +aRow,1000,U64 +aCol,1000,U64 +bCol,500,U64 +sketchDimension,25,U64 +ptFile,torchscripts/RAWMM.pt,String +threads,1,U64 +forceMP,1,U64 +algoDelta,0.02,Double diff --git a/benchmark/scripts/scanAlgoDelta/drawTogether.py b/benchmark/scripts/scanAlgoDelta/drawTogether.py new file mode 100755 index 00000000..aefede61 --- /dev/null +++ b/benchmark/scripts/scanAlgoDelta/drawTogether.py @@ -0,0 +1,177 @@ +#!/usr/bin/env python3 +import csv +import numpy as np +import accuBar as accuBar +import groupBar as groupBar +import groupBar2 as groupBar2 +import groupLine as groupLine +from autoParase import * +import itertools as it +import os + +import matplotlib +import numpy as np +import pylab +import matplotlib.font_manager as fm +from matplotlib.font_manager import FontProperties +from matplotlib.ticker import LogLocator, LinearLocator +import os +import pandas as pd +import sys +from OoOCommon import * +import time + +# OPT_FONT_NAME = 'Helvetica' +TICK_FONT_SIZE = 22 +LABEL_FONT_SIZE = 28 +LEGEND_FONT_SIZE = 30 +LABEL_FP = FontProperties(style='normal', size=LABEL_FONT_SIZE) +LEGEND_FP = FontProperties(style='normal', size=LEGEND_FONT_SIZE) +TICK_FP = FontProperties(style='normal', size=TICK_FONT_SIZE) + +MARKERS = (['*', '|', 'v', "^", "", "h", "<", ">", "+", "d", "<", "|", "", "+", "_"]) +# you may want to change the color map for different figures +COLOR_MAP = ( + '#B03A2E', '#2874A6', '#239B56', '#7D3C98', '#FFFFFF', '#F1C40F', '#F5CBA7', '#82E0AA', '#AEB6BF', '#AA4499') +# you may want to change the patterns for different figures +PATTERNS = (["////", "o", "", "||", "-", "//", "\\", "o", "O", "////", ".", "|||", "o", "---", "+", "\\\\", "*"]) +LABEL_WEIGHT = 'bold' +LINE_COLORS = COLOR_MAP +LINE_WIDTH = 3.0 +MARKER_SIZE = 15.0 +MARKER_FREQUENCY = 1000 + +matplotlib.rcParams['ps.useafm'] = True +matplotlib.rcParams['pdf.use14corefonts'] = True +matplotlib.rcParams['xtick.labelsize'] = TICK_FONT_SIZE +matplotlib.rcParams['ytick.labelsize'] = TICK_FONT_SIZE +matplotlib.rcParams['font.family'] = OPT_FONT_NAME +matplotlib.rcParams['pdf.fonttype'] = 42 + +scanTag = "algoDelta" + + +def singleRun(exePath, singleValue, resultPath, configTemplate): + # resultFolder="singleValueTests" + configFname = "config_" + scanTag + str(singleValue) + ".csv" + # configTemplate = "config.csv" + # clear old files + os.system("cd " + exePath + "&& sudo rm *.csv") + + # editConfig(configTemplate, exePath + configFname, "earlierEmitMs", 0) + editConfig(configTemplate, exePath + configFname, scanTag, singleValue) + # prepare new file + # run + os.system("cd " + exePath + "&& sudo ./benchmark " + configFname) + # copy result + os.system("sudo rm -rf " + resultPath + "/" + str(singleValue)) + os.system("sudo mkdir " + resultPath + "/" + str(singleValue)) + os.system("cd " + exePath + "&& sudo cp *.csv " + resultPath + "/" + str(singleValue)) + + +def runScanVector(exePath, singleValueVec, resultPath, templateName="config.csv"): + for i in singleValueVec: + singleRun(exePath, i, resultPath, templateName) + +def readResultSingle(singleValue, resultPath): + resultFname = resultPath + "/" + str(singleValue) + "/default.csv" + elapsedTime = readConfig(resultFname, "perfElapsedTime") + cacheMiss = readConfig(resultFname, "cacheMiss") + cacheRefs = readConfig(resultFname, "cacheRefs") + froError = readConfig(resultFname, "froError") + errorBoundRatio = readConfig(resultFname, "errorBoundRatio") + return elapsedTime, cacheMiss, cacheRefs, froError, errorBoundRatio + + +def cleanPath(path): + os.system("sudo rm -rf " + path) + os.system("sudo mkdir " + path) + + +def readResultVector(singleValueVec, resultPath): + elapseTimeVec = [] + cacheMissVec = [] + cacheRefVec = [] + froErrorVec = [] + errorBoundRatioVec = [] + for i in singleValueVec: + elapsedTime, cacheMiss, cacheRefs, froError, errorBoundRatio = readResultSingle(i, resultPath) + elapseTimeVec.append(float(elapsedTime) / 1000.0) + cacheMissVec.append(float(cacheMiss)) + cacheRefVec.append(float(cacheRefs)) + froErrorVec.append(float(froError)) + errorBoundRatioVec.append(float(errorBoundRatio)) + return np.array(elapseTimeVec), np.array(cacheMissVec), np.array(cacheRefVec), np.array(froErrorVec), np.array( + errorBoundRatioVec) + + +def compareMethod(exeSpace, commonPathBase, resultPaths, csvTemplates, periodVec, reRun=1): + elapsedTimeAll = [] + cacheMissAll = [] + cacheRefAll = [] + periodAll = [] + froAll = [] + errorBoundRatioAll = [] + for i in range(len(csvTemplates)): + resultPath = commonPathBase + resultPaths[i] + if (reRun == 1): + os.system("sudo rm -rf " + resultPath) + os.system("sudo mkdir " + resultPath) + runScanVector(exeSpace, periodVec, resultPath, csvTemplates[i]) + elapsedTime, cacheMiss, cacheRef, fro, eb = readResultVector(periodVec, resultPath) + elapsedTimeAll.append(elapsedTime) + cacheMissAll.append(cacheMiss) + cacheRefAll.append(cacheRef) + periodAll.append(periodVec) + cacheMissRateAll = np.array(cacheMissAll) / np.array(cacheRefAll) * 100.0 + froAll.append(fro) + errorBoundRatioAll.append(eb) + # periodAll.append(periodVec) + return np.array(elapsedTimeAll), cacheMissRateAll, periodAll, np.array(froAll), np.array(errorBoundRatioAll) + + +def main(): + exeSpace = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/" + commonBase = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/results/" + scanTag + "/" + figPath = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/figures/" + scanTag + methodTags = ["TOW", "MM"] + resultPaths = ["tow", "mm"] + csvTemplates = ["config_CPPTOW.csv", "config_RAWMM.csv"] + valueVec = [0.2, 0.1, 0.02, 0.005, 5e-4, 2e-9, 9e-14, 2e-22, 3e-44] + valueVecDisp = np.array(valueVec) + # run + reRun = 0 + if (len(sys.argv) < 2): + os.system("mkdir ../../results") + os.system("mkdir ../../figures") + os.system("mkdir " + figPath) + os.system("sudo rm -rf " + commonBase) + os.system("sudo mkdir " + commonBase) + reRun = 1 + + elapsedTimeAll, cacheMissAll, periodAll, fro, eb = compareMethod(exeSpace, commonBase, resultPaths, csvTemplates, valueVec, + reRun) + groupLine.DrawFigure(periodAll, elapsedTimeAll, + methodTags, + "value of delta", "elapsed time (ms)", 0, 1, + figPath + "/" + scanTag + "_elapsedTime", + True) + groupLine.DrawFigureYnormal(periodAll, cacheMissAll, + methodTags, + "value of delta", "cacheMiss (%)", 0, 1, + figPath + "/" + scanTag + "_cacheMiss", + True) + + groupLine.DrawFigureYnormal(periodAll, + fro * 100.0, + methodTags, + "value of delta", "normalized error %", 0, 1, figPath + "/" +scanTag + "_froError", + True) + groupLine.DrawFigureYnormal(periodAll, + eb * 100.0, + methodTags, + "value of delta", "error bound ratio %", 0, 1, figPath + "/" + scanTag + "_ebRatio", + True) + +if __name__ == "__main__": + main() diff --git a/benchmark/scripts/scanAlgoDelta/groupBar.py b/benchmark/scripts/scanAlgoDelta/groupBar.py new file mode 100755 index 00000000..ef2d9842 --- /dev/null +++ b/benchmark/scripts/scanAlgoDelta/groupBar.py @@ -0,0 +1,236 @@ +import itertools as it +import os + +import matplotlib +import matplotlib.pyplot as plt +import numpy as np +import pylab +from matplotlib.font_manager import FontProperties +from matplotlib.ticker import LogLocator, LinearLocator + +OPT_FONT_NAME = 'Helvetica' +TICK_FONT_SIZE = 24 +LABEL_FONT_SIZE = 28 +LEGEND_FONT_SIZE = 15 +LABEL_FP = FontProperties(style='normal', size=LABEL_FONT_SIZE) +LEGEND_FP = FontProperties(style='normal', size=LEGEND_FONT_SIZE) +TICK_FP = FontProperties(style='normal', size=TICK_FONT_SIZE) + +MARKERS = (["", 'o', 's', 'v', "^", "", "h", "<", ">", "+", "d", "<", "|", "", "+", "_"]) +# you may want to change the color map for different figures +COLOR_MAP = ( + '#7FFFFF', '#B03A2E', '#2874A6', '#FFFFFF', '#7FFFFF', '#B03A2E', '#2874A6', '#FFFFFF', '#F5CBA7', '#82E0AA', + '#AEB6BF', + '#AA4499') +# you may want to change the patterns for different figures +PATTERNS = ( + ["////", "\\\\", "//", "o", "*", "||", "-", "//", "\\", "o", "O", "////", ".", "|||", "o", "---", "+", "\\\\", "*"]) +LABEL_WEIGHT = 'bold' +LINE_COLORS = COLOR_MAP +LINE_WIDTH = 3.0 +MARKER_SIZE = 15.0 +MARKER_FREQUENCY = 1000 + +matplotlib.rcParams['ps.useafm'] = True +matplotlib.rcParams['pdf.use14corefonts'] = True +matplotlib.rcParams['xtick.labelsize'] = TICK_FONT_SIZE +matplotlib.rcParams['ytick.labelsize'] = TICK_FONT_SIZE +matplotlib.rcParams['font.family'] = OPT_FONT_NAME +matplotlib.rcParams['pdf.fonttype'] = 42 + +exp_dir = "/data1/xtra" + +FIGURE_FOLDER = exp_dir + '/results/figure' + + +def DrawLegend(legend_labels, filename): + fig = pylab.figure() + ax1 = fig.add_subplot(111) + FIGURE_LABEL = legend_labels + LEGEND_FP = FontProperties(style='normal', size=26) + figlegend = pylab.figure(figsize=(16, 0.5)) + bars = [None] * (len(FIGURE_LABEL)) + data = [1] + x_values = [1] + + width = 0.3 + for i in range(len(FIGURE_LABEL)): + bars[i] = ax1.bar(x_values, data, width, + hatch=PATTERNS[i], + color=LINE_COLORS[i], + label=FIGURE_LABEL[i], + edgecolor='black', linewidth=3) + + # LEGEND + + figlegend.legend(bars, FIGURE_LABEL, prop=LEGEND_FP, \ + loc=1, ncol=len(FIGURE_LABEL), mode="expand", shadow=True, \ + frameon=True, handlelength=2, handletextpad=0.3, columnspacing=0.5, + borderaxespad=-0.2, fancybox=True + ) + figlegend.savefig(FIGURE_FOLDER + '/' + filename + '.pdf') + + +# draw a bar chart +def DrawFigure(x_values, y_values, legend_labels, x_label, y_label, y_min, y_max, filename, allow_legend): + # you may change the figure size on your own. + fig = plt.figure(figsize=(10, 3)) + figure = fig.add_subplot(111) + + FIGURE_LABEL = legend_labels + + # values in the x_xis + index = np.arange(len(x_values)) + # the bar width. + # you may need to tune it to get the best figure. + width = 0.08 + # draw the bars + bars = [] + ts = 0 + pos = 0 + gl = len(y_values[0]) + for i in range(len(y_values)): + pos = pos + 3 * width + for j in range(len(y_values[i])): + pos = pos + width + bar = plt.bar(pos, y_values[i][j], width, hatch=PATTERNS[j], color=LINE_COLORS[j], label=FIGURE_LABEL[j], + edgecolor='black', linewidth=3) + bars.append(bar) + ts = ts + 1 + + # sometimes you may not want to draw legends. + if allow_legend == True: + plt.legend(bars, FIGURE_LABEL, + prop=LEGEND_FP, + ncol=4, + loc='upper center', + # mode='expand', + shadow=False, + bbox_to_anchor=(0.45, 1.6), + columnspacing=0.1, + handletextpad=0.2, + # bbox_transform=ax.transAxes, + # frameon=True, + # columnspacing=5.5, + # handlelength=2, + ) + + # you may need to tune the xticks position to get the best figure. + plt.xticks(index, x_values) + # plt.ticklabel_format(axis="y", style="sci", scilimits=(0, 0)) + # plt.grid(axis='y', color='gray') + # figure.get_xaxis().set_major_formatter(matplotlib.ticker.ScalarFormatter()) + + # you may need to tune the xticks position to get the best figure. + # plt.yscale('log') + # + # plt.grid(axis='y', color='gray') + figure.yaxis.set_major_locator(LinearLocator(5)) + # figure.xaxis.set_major_locator(LinearLocator(5)) + figure.get_xaxis().set_tick_params(direction='in', pad=10) + figure.get_yaxis().set_tick_params(direction='in', pad=10) + + plt.xlabel(x_label, fontproperties=LABEL_FP) + plt.ylabel(y_label, fontproperties=LABEL_FP) + plt.ylim(y_min, y_max) + plt.savefig(filename + ".pdf", bbox_inches='tight') + + +# example for reading csv file +def ReadFile(): + y = [] + col1 = [] + col2 = [] + col3 = [] + col4 = [] + col5 = [] + col6 = [] + col7 = [] + col8 = [] + col9 = [] + + for id in it.chain(range(38, 42)): + col9.append(0) + y.append(col9) # this is a lz4_pipe2 empty line to separate eager and lazy. + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/NPJ_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get the 99th timestamp + col1.append(x) + y.append(col1) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/PRJ_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get the 99th timestamp + col2.append(x) + y.append(col2) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/MWAY_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get the 99th timestamp + col3.append(x) + y.append(col3) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/MPASS_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get the 99th timestamp + col4.append(x) + y.append(col4) + + y.append(col9) # this is a lz4_pipe2 empty line to separate eager and lazy. + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/SHJ_JM_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get last timestamp + col5.append(x) + y.append(col5) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/SHJ_JBCR_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get last timestamp + col6.append(x) + y.append(col6) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/PMJ_JM_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get last timestamp + col7.append(x) + y.append(col7) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/PMJ_JBCR_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get last timestamp + col8.append(x) + y.append(col8) + return y + + +if __name__ == "__main__": + x_values = ["Stock", "Rovio", "YSB", "DEBS"] + + y_values = ReadFile() + + legend_labels = ['Lazy:', 'NPJ', 'PRJ', 'MWAY', 'MPASS', + 'Eager:', 'SHJ$^{JM}$', 'SHJ$^{JB}$', 'PMJ$^{JM}$', 'PMJ$^{JB}$'] + print(y_values) + DrawFigure(x_values, y_values, legend_labels, + '', 'Latency (ms)', 0, + 400, 'latency_figure_app', False) + + # DrawLegend(legend_labels, 'latency_legend') diff --git a/benchmark/scripts/scanAlgoDelta/groupBar2.py b/benchmark/scripts/scanAlgoDelta/groupBar2.py new file mode 100755 index 00000000..31155695 --- /dev/null +++ b/benchmark/scripts/scanAlgoDelta/groupBar2.py @@ -0,0 +1,232 @@ +import itertools as it +import os + +import matplotlib +import matplotlib.pyplot as plt +import numpy as np +import pylab +from matplotlib.font_manager import FontProperties +from matplotlib.ticker import LogLocator, LinearLocator + +OPT_FONT_NAME = 'Helvetica' +TICK_FONT_SIZE = 24 +LABEL_FONT_SIZE = 28 +LEGEND_FONT_SIZE = 30 +LABEL_FP = FontProperties(style='normal', size=LABEL_FONT_SIZE) +LEGEND_FP = FontProperties(style='normal', size=LEGEND_FONT_SIZE) +TICK_FP = FontProperties(style='normal', size=TICK_FONT_SIZE) + +MARKERS = (["", 'o', 's', 'v', "^", "", "h", "<", ">", "+", "d", "<", "|", "", "+", "_"]) +# you may want to change the color map for different figures +COLOR_MAP = ( + '#FFFFFF', '#B03A2E', '#2874A6', '#239B56', '#7D3C98', '#00FFFF', '#F1C40F', '#F5CBA7', '#82E0AA', '#AEB6BF', + '#AA4499') +# you may want to change the patterns for different figures +PATTERNS = ( + ["", "////", "\\\\", "//", "o", "", "||", "-", "//", "\\", "o", "O", "////", ".", "|||", "o", "---", "+", "\\\\", + "*"]) +LABEL_WEIGHT = 'bold' +LINE_COLORS = COLOR_MAP +LINE_WIDTH = 3.0 +MARKER_SIZE = 15.0 +MARKER_FREQUENCY = 1000 + +matplotlib.rcParams['ps.useafm'] = True +matplotlib.rcParams['pdf.use14corefonts'] = True +matplotlib.rcParams['xtick.labelsize'] = TICK_FONT_SIZE +matplotlib.rcParams['ytick.labelsize'] = TICK_FONT_SIZE +matplotlib.rcParams['font.family'] = OPT_FONT_NAME +matplotlib.rcParams['pdf.fonttype'] = 42 + +exp_dir = "/data1/xtra" + +FIGURE_FOLDER = exp_dir + '/results/figure' + + +def DrawLegend(legend_labels, filename): + fig = pylab.figure() + ax1 = fig.add_subplot(111) + FIGURE_LABEL = legend_labels + LEGEND_FP = FontProperties(style='normal', size=26) + figlegend = pylab.figure(figsize=(16, 0.5)) + bars = [None] * (len(FIGURE_LABEL)) + data = [1] + x_values = [1] + + width = 0.3 + for i in range(len(FIGURE_LABEL)): + bars[i] = ax1.bar(x_values, data, width, + hatch=PATTERNS[i], + color=LINE_COLORS[i], + label=FIGURE_LABEL[i], + edgecolor='black', linewidth=3) + + # LEGEND + + figlegend.legend(bars, FIGURE_LABEL, prop=LEGEND_FP, \ + loc=1, ncol=len(FIGURE_LABEL), mode="expand", shadow=True, \ + frameon=True, handlelength=2, handletextpad=0.3, columnspacing=0.5, + borderaxespad=-0.2, fancybox=True + ) + figlegend.savefig(FIGURE_FOLDER + '/' + filename + '.pdf') + + +# draw a bar chart +def DrawFigure(x_values, y_values, legend_labels, x_label, y_label, y_min, y_max, filename, allow_legend): + # you may change the figure size on your own. + fig = plt.figure(figsize=(10, 3)) + figure = fig.add_subplot(111) + + FIGURE_LABEL = legend_labels + + # values in the x_xis + index = np.arange(len(x_values)) + # the bar width. + # you may need to tune it to get the best figure. + width = 0.12 + # draw the bars + bars = [None] * (len(FIGURE_LABEL)) + for i in range(len(y_values)): + bars[i] = plt.bar(index + i * width + width / 2, + y_values[i], width, + hatch=PATTERNS[i], + color=LINE_COLORS[i], + label=FIGURE_LABEL[i], edgecolor='black', linewidth=3) + + # sometimes you may not want to draw legends. + if allow_legend == True: + plt.legend(bars, FIGURE_LABEL, + prop=LEGEND_FP, + ncol=3, + loc='upper center', + # mode='expand', + shadow=False, + bbox_to_anchor=(0.45, 1.7), + columnspacing=0.1, + handletextpad=0.2, + # bbox_transform=ax.transAxes, + # frameon=True, + # columnspacing=5.5, + # handlelength=2, + ) + + # you may need to tune the xticks position to get the best figure. + plt.xticks(index + 3 * width, x_values, rotation=30) + + # plt.ticklabel_format(axis="y", style="sci", scilimits=(0, 0)) + # plt.grid(axis='y', color='gray') + # figure.get_xaxis().set_major_formatter(matplotlib.ticker.ScalarFormatter()) + + # you may need to tune the xticks position to get the best figure. + # plt.yscale('log') + # + # plt.grid(axis='y', color='gray') + figure.yaxis.set_major_locator(LinearLocator(10)) + # figure.xaxis.set_major_locator(LinearLocator(5)) + figure.get_xaxis().set_tick_params(direction='in', pad=10) + figure.get_yaxis().set_tick_params(direction='in', pad=10) + + plt.xlabel(x_label, fontproperties=LABEL_FP) + plt.ylabel(y_label, fontproperties=LABEL_FP) + + plt.savefig(filename + ".pdf", bbox_inches='tight') + + +# example for reading csv file +def ReadFile(): + y = [] + col1 = [] + col2 = [] + col3 = [] + col4 = [] + col5 = [] + col6 = [] + col7 = [] + col8 = [] + col9 = [] + + for id in it.chain(range(38, 42)): + col9.append(0) + y.append(col9) # this is a fake empty line to separate eager and lazy. + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/NPJ_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get the 99th timestamp + col1.append(x) + y.append(col1) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/PRJ_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get the 99th timestamp + col2.append(x) + y.append(col2) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/MWAY_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get the 99th timestamp + col3.append(x) + y.append(col3) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/MPASS_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get the 99th timestamp + col4.append(x) + y.append(col4) + + y.append(col9) # this is a fake empty line to separate eager and lazy. + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/SHJ_JM_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get last timestamp + col5.append(x) + y.append(col5) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/SHJ_JBCR_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get last timestamp + col6.append(x) + y.append(col6) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/PMJ_JM_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get last timestamp + col7.append(x) + y.append(col7) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/PMJ_JBCR_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get last timestamp + col8.append(x) + y.append(col8) + return y + + +if __name__ == "__main__": + x_values = ["Stock", "Rovio", "YSB", "DEBS"] + + y_values = ReadFile() + + legend_labels = ['Lazy:', 'NPJ', 'PRJ', 'MWAY', 'MPASS', + 'Eager:', 'SHJ$^{JM}$', 'SHJ$^{JB}$', 'PMJ$^{JM}$', 'PMJ$^{JB}$'] + print(y_values) + DrawFigure(x_values, y_values, legend_labels, + '', 'Latency (ms)', 0, + 400, 'latency_figure_app', False) + + # DrawLegend(legend_labels, 'latency_legend') diff --git a/benchmark/scripts/scanAlgoDelta/groupLine.py b/benchmark/scripts/scanAlgoDelta/groupLine.py new file mode 100755 index 00000000..8110fd3b --- /dev/null +++ b/benchmark/scripts/scanAlgoDelta/groupLine.py @@ -0,0 +1,366 @@ +import itertools as it +import os +import matplotlib.pyplot as plt +import matplotlib.font_manager as fm +import matplotlib +import numpy as np +import pylab +from matplotlib.font_manager import FontProperties +from matplotlib.ticker import MaxNLocator +from matplotlib.font_manager import FontProperties +from matplotlib.ticker import LinearLocator, LogLocator, MaxNLocator, ScalarFormatter +from numpy import double + +# 获取系统中可用的字体路径 +# font_paths = fm.findSystemFonts() +# OPT_FONT_NAME = 'Helvetica' +TICK_FONT_SIZE = 20 +LABEL_FONT_SIZE = 20 +LEGEND_FONT_SIZE = 20 +LABEL_FP = FontProperties(style='normal', size=LABEL_FONT_SIZE) +LEGEND_FP = FontProperties(style='normal', size=LEGEND_FONT_SIZE) +TICK_FP = FontProperties(style='normal', size=TICK_FONT_SIZE) + +MARKERS = (['o', 's', 'v', "^", "h", "v", ">", "x", "d", "<", "|", "p", "+", "_", "%", "|", "|", "|", "|", "|"]) +# you may want to change the color map for different figures +COLOR_MAP = ( + '#F15854', '#5DA5DA', '#60BD68', '#B276B2', '#DECF3F', '#F17CB0', '#B2912F', '#FAA43A', '#AFAFAF', '#087878', + '#783456', + '#560012', '#431256', "#00AABB", "#AA00BB") +# you may want to change the patterns for different figures +PATTERNS = (["|", "\\", "/", "+", "-", ".", "*", "x", "o", "O", "////", ".", "|||", "o", "---", "+", "\\\\", "*"]) +LABEL_WEIGHT = 'bold' +LINE_COLORS = COLOR_MAP +LINE_WIDTH = 3.0 +MARKER_SIZE = 13.0 +MARKER_FREQUENCY = 1000 + +# matplotlib.rcParams['ps.useafm'] = True +# matplotlib.rcParams['pdf.use14corefonts'] = True +# matplotlib.rcParams['xtick.labelsize'] = TICK_FONT_SIZE +# matplotlib.rcParams['ytick.labelsize'] = TICK_FONT_SIZE +# 创建字体列表 +# Explicitly specify the font path +# 获取系统中可用的字体路径 +font_paths = fm.findSystemFonts() + +# 创建字体列表 +font_list = [] +for font_path in font_paths: + try: + font_name = fm.FontProperties(fname=font_path).get_name() + if font_name not in font_list: + font_list.append(font_name) + except: + pass + +# 配置 matplotlib 使用系统中可用的字体 +plt.rcParams['font.family'] = font_list[0] + +FIGURE_FOLDER = '/data1/xtra/results/figure' + + +# there are some embedding problems if directly exporting the pdf figure using matplotlib. +# so we generate the eps format first and convert it to pdf. +def ConvertEpsToPdf(dir_filename): + os.system("epstopdf --outfile " + dir_filename + ".pdf " + dir_filename + ".eps") + os.system("rm -rf " + dir_filename + ".eps") + + +def DrawLegend(legend_labels, filename): + fig = pylab.figure() + ax1 = fig.add_subplot(111) + FIGURE_LABEL = legend_labels + LINE_WIDTH = 8.0 + MARKER_SIZE = 12.0 + LEGEND_FP = FontProperties(style='normal', size=26) + + figlegend = pylab.figure(figsize=(12, 0.5)) + idx = 0 + lines = [None] * (len(FIGURE_LABEL)) + data = [1] + x_values = [1] + + idx = 0 + for group in range(len(FIGURE_LABEL)): + lines[idx], = ax1.plot(x_values, data, + color=LINE_COLORS[idx], linewidth=LINE_WIDTH, + marker=MARKERS[idx], markersize=MARKER_SIZE, label=str(group)) + idx = idx + 1 + + # LEGEND + figlegend.legend(lines, FIGURE_LABEL, prop=LEGEND_FP, + loc=1, ncol=len(FIGURE_LABEL), mode="expand", shadow=False, + frameon=False, borderaxespad=0.0, handlelength=2) + + if not os.path.exists(FIGURE_FOLDER): + os.makedirs(FIGURE_FOLDER) + # no need to export eps in this case. + figlegend.savefig(filename + '.pdf') + + +# draw a line chart +def DrawFigure(xvalues, yvalues, legend_labels, x_label, y_label, y_min, y_max, filename, allow_legend): + # you may change the figure size on your own. + fig = plt.figure(figsize=(10, 3)) + figure = fig.add_subplot(111) + + FIGURE_LABEL = legend_labels + + x_values = xvalues + y_values = yvalues + + lines = [None] * (len(FIGURE_LABEL)) + for i in range(len(y_values)): + lines[i], = figure.plot(x_values[i], y_values[i], color=LINE_COLORS[i], \ + linewidth=LINE_WIDTH, marker=MARKERS[i], \ + markersize=MARKER_SIZE, label=FIGURE_LABEL[i]) + + # sometimes you may not want to draw legends. + if allow_legend == True: + plt.legend(lines, + FIGURE_LABEL, + prop=LEGEND_FP, + loc='upper center', + ncol=3, + # mode='expand', + bbox_to_anchor=(0.55, 1.6), shadow=False, + columnspacing=0.1, + frameon=True, borderaxespad=0.0, handlelength=1.5, + handletextpad=0.1, + labelspacing=0.1) + plt.xscale('log') + plt.yscale('log') + # plt.yscale('log') + + # you may control the limits on your own. + + # plt.ylim(y_min, y_max) + + plt.grid(axis='y', color='gray') + figure.yaxis.set_major_locator(LogLocator(base=10)) + figure.xaxis.set_major_locator(LogLocator(base=10)) + + figure.get_xaxis().set_tick_params(direction='in', pad=10) + figure.get_yaxis().set_tick_params(direction='in', pad=10) + + plt.xlabel(x_label, fontproperties=LABEL_FP) + plt.ylabel(y_label, fontproperties=LABEL_FP) + + size = fig.get_size_inches() + dpi = fig.get_dpi() + + # plt.show() + plt.savefig(filename + ".pdf", bbox_inches='tight') + + +# draw a line chart +def DrawFigureXYnormal(xvalues, yvalues, legend_labels, x_label, y_label, y_min, y_max, filename, allow_legend): + # you may change the figure size on your own. + fig = plt.figure(figsize=(10, 3)) + figure = fig.add_subplot(111) + + FIGURE_LABEL = legend_labels + + x_values = xvalues + y_values = yvalues + + lines = [None] * (len(FIGURE_LABEL)) + for i in range(len(y_values)): + lines[i], = figure.plot(x_values[i], y_values[i], color=LINE_COLORS[i], \ + linewidth=LINE_WIDTH, marker=MARKERS[i], \ + markersize=MARKER_SIZE, label=FIGURE_LABEL[i], markeredgecolor='k') + + # sometimes you may not want to draw legends. + if allow_legend == True: + plt.legend(lines, + FIGURE_LABEL, + prop=LEGEND_FP, + loc='upper center', + ncol=3, + bbox_to_anchor=(0.55, 1.5), shadow=False, + columnspacing=0.1, + frameon=True, borderaxespad=0, handlelength=1.2, + handletextpad=0.1, + labelspacing=0.1) + # plt.xscale('log') + # plt.yscale('log') + # plt.yscale('log') + + # you may control the limits on your own. + + # plt.ylim(y_min, y_max) + + plt.grid(axis='y', color='gray') + plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号 + # figure.yaxis.set_major_locator(LogLocator(base=10)) + # figure.xaxis.set_major_locator(LogLocator(base=10)) + plt.xticks(rotation=0, fontsize=TICK_FONT_SIZE) + figure.get_xaxis().set_tick_params(direction='in', pad=10) + figure.get_yaxis().set_tick_params(direction='in', pad=10) + + plt.xlabel(x_label, fontproperties=LABEL_FP) + plt.ylabel(y_label, fontproperties=LABEL_FP) + + size = fig.get_size_inches() + dpi = fig.get_dpi() + + # plt.show() + plt.savefig(filename + ".pdf", bbox_inches='tight') + + +# draw a line chart +def DrawFigureYnormal(xvalues, yvalues, legend_labels, x_label, y_label, y_min, y_max, filename, allow_legend): + # you may change the figure size on your own. + fig = plt.figure(figsize=(10, 3)) + figure = fig.add_subplot(111) + + FIGURE_LABEL = legend_labels + + x_values = xvalues + y_values = yvalues + + lines = [None] * (len(FIGURE_LABEL)) + for i in range(len(y_values)): + lines[i], = figure.plot(x_values[i], y_values[i], color=LINE_COLORS[i], \ + linewidth=LINE_WIDTH, marker=MARKERS[i], \ + markersize=MARKER_SIZE, label=FIGURE_LABEL[i], markeredgecolor='k') + + # sometimes you may not want to draw legends. + if allow_legend == True: + plt.legend(lines, + FIGURE_LABEL, + prop=LEGEND_FP, + loc='upper center', + ncol=3, + bbox_to_anchor=(0.55, 1.5), shadow=False, + columnspacing=0.1, + frameon=True, borderaxespad=0, handlelength=1.2, + handletextpad=0.1, + labelspacing=0.1) + plt.xscale('log') + # plt.yscale('log') + # plt.yscale('log') + + # you may control the limits on your own. + + # plt.ylim(y_min, y_max) + + plt.grid(axis='y', color='gray') + plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号 + # figure.yaxis.set_major_locator(LogLocator(base=10)) + # figure.xaxis.set_major_locator(LogLocator(base=10)) + plt.xticks(rotation=0, fontsize=TICK_FONT_SIZE) + figure.get_xaxis().set_tick_params(direction='in', pad=10) + figure.get_yaxis().set_tick_params(direction='in', pad=10) + + plt.xlabel(x_label, fontproperties=LABEL_FP) + plt.ylabel(y_label, fontproperties=LABEL_FP) + + size = fig.get_size_inches() + dpi = fig.get_dpi() + + # plt.show() + plt.savefig(filename + ".pdf", bbox_inches='tight') + + +# example for reading csv file +def ReadFile(): + y = [] + col1 = [] + col2 = [] + col3 = [] + col4 = [] + col5 = [] + col6 = [] + col7 = [] + col8 = [] + + for id in it.chain(range(28, 32)): + file = '/data1/xtra/results/timestamps/PRJ_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(len(read) - 1).strip("\n")) # get last timestamp + value = len(read) / x # get throughput (#items/ms) + col1.append(value) + y.append(col1) + + for id in it.chain(range(28, 32)): + file = '/data1/xtra/results/timestamps/NPJ_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(len(read) - 1).strip("\n")) # get last timestamp + value = len(read) / x # get throughput (#items/ms) + col2.append(value) + y.append(col2) + + for id in it.chain(range(28, 32)): + file = '/data1/xtra/results/timestamps/MPASS_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(len(read) - 1).strip("\n")) # get last timestamp + value = len(read) / x # get throughput (#items/ms) + col3.append(value) + y.append(col3) + + for id in it.chain(range(28, 32)): + file = '/data1/xtra/results/timestamps/MWAY_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(len(read) - 1).strip("\n")) # get last timestamp + value = len(read) / x # get throughput (#items/ms) + col4.append(value) + y.append(col4) + + for id in it.chain(range(28, 32)): + file = '/data1/xtra/results/timestamps/SHJ_JM_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(len(read) - 1).strip("\n")) # get last timestamp + value = len(read) / x # get throughput (#items/ms) + col5.append(value) + y.append(col5) + + for id in it.chain(range(28, 32)): + file = '/data1/xtra/results/timestamps/SHJ_JBCR_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(len(read) - 1).strip("\n")) # get last timestamp + value = len(read) / x # get throughput (#items/ms) + col6.append(value) + y.append(col6) + + for id in it.chain(range(28, 32)): + file = '/data1/xtra/results/timestamps/PMJ_JM_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(len(read) - 1).strip("\n")) # get last timestamp + value = len(read) / x # get throughput (#items/ms) + col7.append(value) + y.append(col7) + + for id in it.chain(range(28, 32)): + file = '/data1/xtra/results/timestamps/PMJ_JBCR_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(len(read) - 1).strip("\n")) # get last timestamp + value = len(read) / x # get throughput (#items/ms) + col8.append(value) + y.append(col8) + return y + + +if __name__ == "__main__": + # x_values = ['Unique', 'Zipf(0)', 'Zipf(0.2)', 'Zipf(0.4)', 'Zipf(0.8)', 'Zipf(1)'] + x_values = [1600, 3200, 6400, 12800, 25600] + + y_values = ReadFile() + + legend_labels = ['NPJ', 'PRJ', 'MWAY', 'MPASS', 'SHJ$^{JM}$', 'SHJ$^{JB}$', 'PMJ$^{JM}$', + 'PMJ$^{JB}$'] + + DrawFigure(x_values, y_values, legend_labels, + 'Input arrival rate of R (e/ms)', 'Tpt. (#matches/ms)', x_values[0], + x_values[4], 'throughput_figure1_1', False) + +# DrawLegend(legend_labels, 'factor_legend') diff --git a/benchmark/scripts/scanAlgoDelta/perfRu.csv b/benchmark/scripts/scanAlgoDelta/perfRu.csv new file mode 100644 index 00000000..9ee43623 --- /dev/null +++ b/benchmark/scripts/scanAlgoDelta/perfRu.csv @@ -0,0 +1,7 @@ +key,value,type +cacheMiss,12491377,U64 +cacheRefs,35327177,U64 +cpuClock,2478812100,U64 +cpuCycle,9889422467,U64 +instructions,16997458033,U64 +taskClock,2478813000,U64 diff --git a/figures/algoBeta/algoBeta_cacheMiss.pdf b/figures/algoBeta/algoBeta_cacheMiss.pdf new file mode 100644 index 0000000000000000000000000000000000000000..f59eaf14da0c3235645ba0a0c1341e1a71df03f0 GIT binary patch literal 7700 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 QAt{ZNV&vynzNo_ZKY1i6DgXcg literal 0 HcmV?d00001 diff --git a/figures/algoBeta/algoBeta_elapsedTime.pdf b/figures/algoBeta/algoBeta_elapsedTime.pdf new file mode 100644 index 0000000000000000000000000000000000000000..e20e820412f899e58d839694361a54b8f409318a GIT binary patch literal 7725 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 literal 0 HcmV?d00001 diff --git a/figures/algoBeta/algoBeta_froError.pdf b/figures/algoBeta/algoBeta_froError.pdf new file mode 100644 index 0000000000000000000000000000000000000000..189352e2d0032ec8210c229b6c6dced6a0e94ec4 GIT binary patch literal 7522 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 literal 0 HcmV?d00001 diff --git a/figures/algoDelta/algoDelta_cacheMiss.pdf b/figures/algoDelta/algoDelta_cacheMiss.pdf new file mode 100644 index 0000000000000000000000000000000000000000..9ae6e51181b6cfaa9bc6d5a5e922fe9de88bc615 GIT binary patch literal 8432 zcmb_ic|4SD)Rx`YCCWOM?94u9?7L*&vxYHt#xf-PzGRCmC0kS^36<TnP<*@?&m(|+~+=*=Uh%2sA)(-q~L&)6|aD|8vqa>7>ILl z1IWn%K_=(Du|SZjJ>K2}=L`fH*gIqWfKY;h5l}$^fc0`DDx!Xypn>zk17U{>pfmao zZdeQ+DE%v$RDG=IE*nC540jI ztENFP1sjM5g0wsdCaC=QRQ>U(1+@9i9LS#z5bY*f?~5f^_uYJu5!Mgq?~5V$L$sf; zzAo0$)m{Y`NLUd}_(4L^QZOVO2!kM{U?{>0AXS2Igd6w)(cdjp_VU6JzCnoEzsG|( z{4;<$STAS13lQ>SQ4LoQg3CaVh6f=IYFG@;5lgh(5ATb$_XGsy^_{W8nV{(wcjZ<= z31*fwJVKYo>QQNUi;EY_O|P+lnu@Nm4&s^d?ECv+{q;^kPE5nLrxDmxciCO8@LIoG z{mPcGF`MSV0H?6fanGgFDbJ-o&5+6z81MS7Q`7ml0so~n{K!eMY~!}=z0difH4;p9 zyC1$*29J93K3ZdI7-(RvhyJ8g>49BSrq9lrVwbO$${N5Omk>;?V)F7ina zWOPXCRXVH7xzuVCz-|*eoi5P3jDEwsq2kNs%MhK)$oHD6JA~D@jtqT|zN!G`%7+GA zQCap!b#QFv9ew4P8A?FIY4{?Y#wgd@w@oBI6 z8$C5yC36gC^=%-t$k6RJ$}D2ukU#^_YA5hbgUuqgU3{-aZ6O`!dss9d-2{$t zpgDOgZTOgFTS1ccfp&dmUB6V{mMDF1MwKKNoz9w-X=}^)fj?HE8HT&N72aY9BfB@? zG=3bzI)79~CkH#q$bC8P0sFk|TvfpC$_AQRyy2y}p+CF|C-0mSw4DOVd-i z6ji*(KMR9NO8`3CS751i3k%k#Zxjni^ADfg*V5S;OBS$*%Ef*t?YPQ~^clFPDj!s!f2FQ_pIqH7R~ z22>BJB}9bv&KS2-Ej8CbZn|jqryE|xzZakvdwdzig)xMzX|RrICRE#S8WzUrB(gas zT%X{2EF+hDprcl;)r>QGC7r=OsuYj#I+N&&MHbsTiTq*F-F;r zFV1U7embGbF|0b;Zl1?=_f~NmwWShC`Fq)kJQ$^HW<%4>v^jw3&Sz@!_naG3r3oub zH8**h={wPhB8^(NuO!7<4{_gFrF<8W>CG&t;>pGdag0ltbvNZMk%njFu#jIl5pnEP zb#vWd%MRbf%v#OJ<44CjQ(vRqMwKtRJxKpJC^TLXPWKDzZM890(y zGQbWMq7N&^nFLPwbg+tMA@;J7oq(qf$~`5fAE_$Ffg8Zf&u(-TI;3b&K#qLa8xGdL zI^ka0yWtkieRqM%+)L2NPrJ1~Slc|yc=XHe$LOAhv=z+i$IXFFdDX(?F|UJ{*DzEO zC)iGl4-KL0ZeF-Va=$&6dg#%N;!^`(%3~FCCl1*74O48S0b|#CH@!5DTu$!ge)io|2||8f)WsG2NG6I@Q^5c`7-|KKN^_T~yVY+>Bg8pWf?Bc_|;Y z%AS0hf9KPY$0H10*`h6CxKL0yEx}I8Dx6`q#*1G$&tBH{3P%g0uhS?=FqDuR0|aFh zg){)8wE1r$ygS(uk|H-Gq~7s~?cFF!CyT$wcX3OavhS9P>I12nNfo2^@>!8KdQc`GEoDPZ%)g1>A6 zjFGi1_Jq~**{>Vh=JRcPQ}u0m1+>TU_@-y!cGlDe2siPwy$9hBkK9XLZn{nac%o8O zNUj>UEPP1|tp1=yPd-^9u9jz6cgdqq5jra-G zhgd}vS^;hTk`eLuCtiIA{6iE68T&in5AmNUgaAP*_I}v!Bd4$)0a&~%#vTAt_acB8 z5w=0*u3pMsey)EBe*J*}B_ia{6}}@P1c-p3;6Tt1e1suTFaj$62Rgnm4?bgJo^jXj zLxETBYTTr*^ac2!+=TRnlo?pHdh$RSv&kuyxR;cPPgRxZWz^JTb^uJe!U`kn2!?(q zi+PbD4`kxvEa7}Vc6=p>NfyKislhBXoGpDXH_#uyv=`vKba!{lw*OtZjDPui^Ccfz zI}*E_dX!%?Kld;y9Y0PoW{?r5e+4Eh5c=lXvB#xHafKNWkY`&vjdQ{_)5lP6heeaA zm<6{v*~C_aET+zH{Q0&gi4oQMC-!3v+Qav_Mo7Gc)@9l5NIZNrZ-_}aNM20%meCp8 zt66DH+Ljn!k~D=qS#*OPZj~r4VQZG&y0tvZGFK>^|1C=Hp|HqOABTY|`6)?Y<5qQ0eBQ}>EzeMPGw%bL!oPJIQ zgYhNQXz81qr+IDfz^ce3BG+H68f~kT1>~@?DQ|WdZOt$S%2U)x|XENLFkwlWWvckA;Q%|Q>{D9 z3))UKMWaB?-C=w4EEU-Jgdi2h^Iq#05bCIm&S!e(;eeyt?EwYKJez@#M+JU zUAaz@Q%}w4ao}KbMsra^I9_<=CQB7s2epPO+7zArl?6F6dt|{;w!H;WfW9m3a z%EPMAWq$Q@7d#`h*W{iKn~ZfyF;{-_rbXJ_yq|4UDDlSl+sBJ{*m7HGpE^!-NgR)X z$2hXe?^+&zTLMl$3ut=XVY!hSV4-{n!l1>#LF zRk1lo31)xay(Q(JDpY976tHPiVwq#sQ(wW{lHvD&wr9&qjDO?2b*^^8#;mE^Z8*T5 zqYF7Fbisr>C5mkYe;(B*OgnK}h29`pv?`_yvBts`t@c@k+X682B6;qi%OcONn0+N? z^19Vv)H^Ws#v9H|_o_j9dT*oKv(VFYaT8fWJ&?YUg&>jMeXjtIxxvD!0Cjg<6k7KQ zAlT1*G*1GZ;VkWAbyOxQ*HQD^iv!m+x4FR+el^Rwul4mlR?DEJ^BqrEsFiaiYAK-Q z!8c_*=NP_R&7O2TYhw4h!XuTp(V~a*YS}7IOP&`mcCl=t(%qN)PAbnAr6zHmd06zo zpxyL@xif8w##Kbk-Qn@+AqCRR+SGtI8Z1edbS|LBU6G>0B*K?j6Vi->U3&|fgWusk zPRr^Dd%dm~@Pcs{3Rpg-aFdj{GMz3lF8ow2rR*5igY&lC?Q!Jh^4S}hE$~!K`;4!} z$e^&cLW?b}f{j7)lQ^bFpHF{CzB%};!u-@YLZ)%gLzn{IG&MdnJyD>B?oP#YsX|P$ zeKk6B11|`Sv%04o^Jp0B*$8`d^Bj*yX75d;{^nUXL9+X{8+a9u=+Md|%zOORcl#b= z!9G%@qM+P>})HwCK00u%FH7=d}#C(Cg(UvzqwD!T? z=BVx>M1BZQUOXiBjZ^X<4l&MZTnJ&k+KbjN7+7*Q@4dbIw0nYDGXFhwJ+I{5J6vXN zW}n5ABp#Y7>#CWymUoLyGNV{rpGI;~MV``%HQc_JnZ7qa51+{VYEffcYYDfcA2i+2 zSkgI-srlM|_W8HvxudtO?p4Bi7c}|RG%=WYv6tZ5wR+dvO|F-ulD%!iKMkp#G@Nr+ zX^nr`m^{cB!!io4ilZ2P>)^I*uW);)bh5H~cX@K26K-{fiZXVxgG7?Kc0ZsqF8g@C z)5YAFwP&{98c4!UD{0DJyG|#v;>qo~@-#;}vrXGV%Rwq%c!GPrHrN5%Z9nwPEgdue zh4ECP5b#!v8@2X3p)hhrVK^7l$HWh5&G!U9O?8Y;pMNu`EnF~lZe}-m^mK1OHoS*U zzeHfsW3Tizn#)-O)$IRbfXCLSH z8WD6S4Q728Ls>2aSFYhx+a>HoLBt8NHafAYm+Q`x`9l6Sla^f%WofkS?BDp^uUmS4 zlDi_l9ek{2*5?exRb|fpIHhnTx$(FJauPg=DtvSAmhB zy|Hz)=j}&KrT5g;;>W>AppV=P0i};&)zs;#0cS8u;aN(pP=0V|_Gxo#*BjqquxNeE@axl4^$V$+F%FyYrB# zT=Iy?I+#nSo-34Qgd_zdGvw@*FfB8qWOP=w!|p1govpmYD!#H{aI9PK#wU;9uJJ9B zylHv1nJ0sb4OCH>dsn4?9<)jX9Afp08~mTvHBmH}_nroI*TkT%1h16TI8JZEJh(8P9gW)SC~Z zpwZ^OS8q&B-#mXSXp_yd+cm5i(}ySBIt3-OaFy4F4Ck|IXy&vmhVg|yAG2cC8kZGT zLn|Cuyxmb$)-fm=3_R$$SUdfCk~g5AuIFW_ipL=1o8zG+0Cm;<*`V>1KZG{H>L1i`UFFJ(Ctu)-BFn942jr~QQNrhVW(0Hgkb8XnInOMLI=L@>C1~+m+ZUbI4%*${+uXgf;Cgb`NIaH* z*lgZ=B(HS>t@vZT6Xbm2fj1s_;xfwVISJAUKQTBN{S0y z=LFS$U3XX9SDrD)tOs%I+s@?ZeJhrX4xjBr8hP}#xfe1njegtN^==YdgGHL>?a0!G zz3=PIyz`~Q}M9x)Uc<~d}EK)B|Wg1(dPM9 z%Jl7pA=N<^RT?sP*N_UCyPm`P8MGIuHUlE(VGHa|rlQ~(kKz2WUh3-4_OEK69*FLoGv$A&l7%O}3 zZy*?~C970sj`Gz#jS!FaiEZ;$%-*ejp4Pi}hQI2JU3wd~y3S;V#hBx4Mr0bTMA_rc z#|yO2j=p8CJ2j&cxmtbsLsu8wWq~#3NJiRc{eZ>suxEfL6tm1Bkw=$k^E3;VZrI;E z2D{t=`!Z)us{ofzRuuG3<#DFX+brsErU@}x|Cj0&~WmWXPL+~W?KR%GQ4(qTFd0!y)CXq+oftnehSW8lgO zTXvbuo|(#5+fFHNX+NTN;3wbOwBvnh!W%gY7nLKuLn=x7h&)%TU1Ct}jIL{$i9;Ec zDme%J>?@H$rHMH2=d^TY2EyQk=TYQtl4a{fI?>P-67dXHiao09-lEJ`qJS3>uz@F@ z9^D7=RQp3mzTMS-e)fpB3t;bGo^b!A(TYI-_haNrUn30(kVLheb$=@StWAf;>Wp%O zU|QDm`=65=mpq#l$VvYGiWpcXlVc{4|I-90v9J60CtDzt&@}$fM_C&~dG|+Prm0PF zFP*reF`6gQkQn^>#oFg9tkALH9%?tO?v0u7v!N)jTS`H%8n;s$k2WJgDH#lJ8(&nY zQ>ln~`3&E~Qp+b~Cd+vLR-Zm=tyHLNr}Z1UKB&4!UwL)b`q7^L<&)h<^9ph`@3V?Zm}yrJV~cyU zq{#A@EXvYn3f7o8f@_(A=xC?d+ML|?mVG|>yaiX9)P*Jw3DtG%9f_@rhy58)2$3xK z8PI=iMyP735t|UiG3f6-2^C#KLp3vTHLRPxnZL2UmmdH`P&Gd9hsSzqc{$;LL_Wg^ z>+DKslbi>NC=;j)tSAtq@9T*5CH5~wv>XY|eOLT>g3#FC+uH-{Nn{Ja#Qr>pxS|@? z5990VjmP-{AwM_@b0CyRHW(4O0WCEXoTiqVuDv%9@|_>})&GF}&XD}8Q$!*7KfL*? zu>$&OspKgjh-ej|<74lIC)(&oATJI>Xhb9|OmL=Nu7@1MVV?fZQ5<^kXPkfY@z7^I zdrty!@<(V72@GdHAPo9FG%DX|6G;e|5D!T>5=Jlr4JWW3Fc{GeWul3AAR0&L8%a z2!YqN4>WgmBv33U0!i~Ly3&n5kyET zeJ6$Dhy`~uWfEk4|2B)Nz*8fUmGIBzyG4o84P?dS3R)-8t#!hibH=_9Sd;{Z32cDH z_qiNw*{r)9te#cU?gpI--SoiSgd`q0>nLs+JWx?>u+6;BkvzDgAF&7fB{^De?d`;H zna2Jd|K$_b)_T??urxs2pSJ!ESl>?F3q^G8@!lRdyoaj;FaRbcEd`MPy5RBNelj4C=U+ooIA3Q`0LZ`>=je|iFrdHB z@^*9rI@n{}39J0L1EB;T-rg1GrA8!-Mbu=VU?>cXgh0V?I1~!C6b1as#Xw)I695c^ z!U5pFUO*%Q0YdnBQ;CJ@?*o&OP^@&+q#sVxX=m4Fw?pB9Gn!A65dO zKnRd<-Wi~v00f)(xnqG~H8c_JN^k^%4bYBQFCdJhU<6cB0$}m>WJTHEI%pE`L?C=$ z0en{fyfYR<1j>B>so_i1GA5#lSRmrNzyM7oVm5)*Z0v-#$Kf4;s2{DK1dK73 z2(%(itFB2h1?x)$g0rRwMaF8o&!E_uWDjJf1-M1tn|$ z9uIQ!&j9LT@s30%AZZ-34pE*Z9| z_f6YW$Bl$N&+1paZWlU2#ldkUI6?M0dNA0>qPTiDNU3TFzuuupFA-0}tZQzbH2d(G zrg}EO4Ib`XFLt~pc4UnG5(S5_l~WyWIleK*R)~H5}rF-Ka>@Q4ybkh(C918 zPMuo2i)1213?HBmqW&^*w8Y2GTRSrQ@>J8qwdOe_l%Dg##f+y*dGj1=btrx`Khg2E zooiQy0*!I|jJPea50-XdpnvSZu86m0$N7O6g~`Tfj?T{fhE?~Pc6V>j^8*idX3^`- z;-aOO;O}c4gG?`$M|s=LN@%+q&}DpE&#TdXb=^atMCIG^-ra_Q?1|}2%`-V+*H%5u z(5+YVIBBxL*^D1+zeGB!g(yL;uN{qMJ?N=57?I{X4(*GmqOd?69U=h5qU6^`P|a{G zCu~A*jQz`_3dU=GoSq61QW@U%DFGS^oG8kx0|}RzmbdT+rZ9D=+qXHYlKc3voFyVM z%f5oL!!*qfoFykC=9)iq4cwv8yC(k{H90CKz`1z_@z|~T0|HDp(Na0XJFYoEJ;(Qo z>a6Q>OP2Sbh@DXM_Fh*ZW8up4cZ%bm&K~XKvrtiYMei(s{=9Oz(l5vMoOPgoQX|(( zrMw`>37({-n^}+W;2xb-+hTtsx^y3VgU+Lt^>3`+&S^)prUuH`HaV6rH!kW19y-Xs zqFMgjk^i}Ey*q6~W7*wKKLA&k`a$KsZ~Ceb7Q4f!Zgms4QcG^r=_b!PP)F z*DFSMDgbWm9ch;wvR}uuMDljL2d|WjHqOtt6>P0ct$geMyw;ohOy+ZnpjQGH zoye@XMq)TK<1J%B1H_9KUd|$~2h&Y8N2)#E4T#?ib6 zQqyj%Gn`r2ug(h1;&e`wKHwS+XPKc(wt@A8hTWLCBc*7Sg;k87L)pVOGxtZs25CoI zMF&8Q;pQdMMX$qCnAcagzd;^e1cQ&@C@pF2qvCyQHgT2YiWE&jnLm@y%;CbjtehG)T1_Opr z>ERe>Ny<<7K(l@v_vu>&0!oSkseYW4H1^eH6^nPfgr`AZu6AMb-f{*kpGsRe?VWCg zF@@!}qkG~WwwG>{)g!;(hQF3ng=` zt8o2jS^32~tnM#AE2CZoFlc<$MdY21(}wE^XFiXA^pYFTRL+U!v_nuxt!RFuibaZK z3Jr?WxN<+D*0sG_sv&Jsk1S{2d@3tj54#~%qgn%pi^Sgc;7;qL?~J;CU&rr_=OHQy zhwGAbAgVrxCp=g3q^Kz>6u7JIUuy?_ikqtTuH zEb7aRev=@|YK6+)fd|w@*rp{=(cT1h*sE6ldhe%OF}Md$ge-Tht|(I4t z5=!Rf$Cy*~4P?0Y(i=xuBNH^8Y^7^$1TOZ$;+q}Xl>*;^*cv{R>RFYOtK^UK{YSmr zF9zfS0Y%8ce-_dGDnb@o0d4-0kt^fRO7guF@7GtbvG;l6eq|;Lp+K-I+6()=X4Q1r=i!EaDNGYm2MchcKw{;d#!>3kx*F#5d5QZ!I84?|E^oT z<`>VJm?u8=n$5tcE<_CJ$y`BnD7=%o5<3bn)`)4(V>daa8qr4^{aQ_#`GmSg_y&MY zPfV$M3CZ%-!D2$Z(-jpxH6~uA{nGxuFeXMABdQL!&~&u)yjjV7==zS2R`?V6>yKyMKoE+l{X+tjdQDQ4AO)M(E#y%L@g5d~@(+E+-)~5ejyzt7mYG zT4(zb=zf06WH@}%d0ala7AcP@_ZsY3ccU<(TUy~cSgF(Xgs+>zU35vFyFlt$!-OFw zYA~So(IT!ZR`P={8;i zHR@B+z>p;xH=3oKXnk>UsY~Z4scM2Zw4(Jb&8nLVD(V7XK3v;6SeYrFa2(MZeKLDo z!jor;d1I=^Jo-|~I8IsubUadKj9R%_fLGAUDAgQx=9|_rwIH2cM&&lsI;0|p2mMyC zu3NobnA7Q=1914!s1j{`bMtuo`Ubq{fKKnWdaKC3m)!{-1}0zB(&MEzIg9s2gm$nd2jXjT6u5a9j2PAH~rG1cMjKXuutkZlw|b-XMfI0y0A6h3!`Ba_I4dI3mGLr)KiN+j4vj#-tT zN-cF4ID)n7K6>jeMM?!VzZ7TO^;qbe7q6Uoo$n zQYM;QbNIl53Aw5^7ib|opPSb}-f^Otrffc|HaV6lW-S$u*lQBKN*P<$tR#;u`&p;z zL@ke*IzL1J(7a8kanUO#{IQ|j^F%+{HZjI`r&XB^VkC;f^N@=id|~QeRrxIdqrEZX z&zz9<%@px2Nwfvp);;Mj-nxtTaUJi- zEb`HCA%x25y#ieHGVf25l1p@y@v!1N5t?eRwcWdiTXY`pIP6t2r}shs%$MR5ax&@m zhb`3e`J%OzY?T)K zyzxa`YsT}7p9o(@S@v4A*Q2LW6P*yV-WKyg011}>Die39d90)pBhA-sM>KAqd`;;4|a~c z%TSkVj>9ymK~0i9H5*fXuLuotxx^lHtsH1s4r;i6LBRD!>wT2|>N#iO15a(2iK?z) zfrXUpJI9J2x4pzdJV3b;;8dSOfyuPD-b#ztb1;^z8X9okBffPiad_(lXb-U0ye_iB zeucWqRxmxVtaN9!UvCPk*h!?$?v&g zS(F%;St2Z%J4}}~r*%(bO1{;f>)DW)JI|q&9(Lvq6&7#K4NV+DSQXIGULJZu zA(dyKd??-FT59;>8{6$lilEcVTJm@9GKtT-@w?5xPLa7$r(>ag9+WQjj(?); z;(2T{y7P^50%l^1^;EPd@IkmUz0N1mAZk`I1RvX%=-K$^PlQ*7U-XaoeeBQ?%NV{e zx*5}dy7evgQVWxQj?k3rPVNUeK1WU2=ia^T0=A|`WukZXJgRnfFegvuFSzHYPli3s z6^6X~eUDVrV$g=5~ zJcEuM`lHv=^64HC{zsAZkb@;-9%pH8s~mY7p?nENZ9FK28iEYTW`2Bf&=rZd*R(v% zf3?xxxCA-EMYy7;5_|3DDfSdl`nO%^!c299bb5KqVJHE3{m#afKZ&6qjhC`SS zxiF0~_HVe3MRH}LjjhAn9yYM$KG9H*9E6}myHvDpB;S#CKQ(k>DCjIj%H^8Vk2IX? zxi=L~KJFBVQR0^VSj5MjTWtBF%B%fR!`XneaObUh=Mdj2|13=USXX_nt?!tGv#yNS z`kM>jh&cJOuaXnvL+y?0~T$1<%;>r72C8Abg?~e1Qzz6tUnFosRgZkrSiJM(5OC*xg3fbLZz+MHXgs z3^WVhTXDVEG`L2QHloNq`l@59k}ec;C_N$E-m%t?|@e!1X+XvgyJ1YJz=5F(a!^qOAsiF9Si<{5a zZEY{S5m@&b{y5tY?tk9){-des$DSEsn`Dm7rY^1UHX_y9DcAuEoT3i2E1gSIE2U;C z=xAWifEBy;puCv6oYJ1f%*II-U4yI+-@TS=Wg{Pk1byBzwe$t5x^}RBJQSD%(BSHQ zHNFw1y$)uE8lBYt%z$I8c?yj_n+iHlVv-tzR2lIEP?wD!0U7eD(u5rZkn$%?u z!hFu~O3WwOE<|?+--1vB@z1K{IET*T4uBl0CW8C9>jzTM|vV!d6?3-0=tN*Blo2>RmqD zJiaxF6WKI6e)(9J*@Sy{T5UV#grSbpNI*Wr{N#gRr(R22y9oK@YN=V-NU3vXIh{%3WNNRx*5?r>8+}^mZ+p9k zsJ^LY_X2V}n*d`b66(sr@2Q=V`zk6I=)YPmf?2koa1t&qnbGfR+eOyxd5&H#L~H%^u!k3@O_#bOJmZB|PyA z+dLt9RC^YqIs)6dY}>ttbbCp3@u<{ILpoIIQVQ2s@Q$zgD41G++qXG}jz(ZW@CB=^ z$0hoj85O|?8`T@3b%7U|12XHL)4qQqANpl!bioGjfj^{*>;2)FcE*6WE|cvHUwM}- zQolapx!}q=CQm!Q#uo4@o_RIbFRX5>lF#-M?`(gIx4yiu4NG6eWG;WX-e{k6!-iRi zRm7M>XocS~y#MKT8H+^;#lFO>zA)sC2fTE61iG}2*;KSf#V(1VpV3;(y+GN#|9Vo= zwsuHT(uNmnVawBHB#X6lk?JVt(el^9$HP1>*Lj{y-Yo8kZ{0b2tmv#=LLIia++>u) znD<;_NIaud-pj_9lZt%_^!46)S(VY9^;?@e+|`5t@!Iy7iKfGw zzUJoQaq#i8AsFg70qj`Lj;y5VSdP@q)a>a8fcrBZ_6X48N~+2)u7bg~rS0q(`leTe~fx<)lTrWiD1YWLPCM6fJ&OGfjU*Y zUaCX=tR61UAa;Z-7wfZ#qmTgnjN~k z?h@>`LV?$i@b*`3uFZRqbi19D+mH2o&QZEM0e1f74fkIlP^8>{zeditRWVQiDb(t@ zc84#Wvw5MpFsf219G}$l^lMDjwA*tfYKp&K!R>Pg6xb;g|1<$cMqK~?W($O&Nbj}( z1;N@FD!Md4*oIe+<8>pl1{hw2LBokl*UEb4xnKibE%eUX&C8>g&IQWiA1M33uUe0* z;(U$*$0oAORP{d6pi`B^dvra)(krqUB}mbMZdv7QloZ3m{k^JmS(-E%^zs2Sk@{!e zf{Lo#hbJ;9C<34G6_^~Dt0{ELem8iNz-K5Yn^;L3_addrd#dyZyAwi?cVVSVnvU?z zGyp_wdtQ&UpZ;CW?re&mR zJ>`;+GSeyU!e+N7fexfkTjV8-W-PMvUMyqtXJQ=Yu5)nNne&+Sn1K|Uln2Iiik83F zp}brkxerVH1GON-_&)>suV93lwmKPvAh*GO$0Sts3=P%Ij;mvx(PrMpXuKByOj0%W z^CDv1wDArEAem_}!aCwe6Z!$gRY;@)Rssmt_q4})lJN_1ZF>^zjwAY!gvQ?P?yguj zGL8=+Bj;f9jOth~j3>^WNbm$gf3OGUKp2?@AVKb=sZ0o3+Uj~}cOdjTa{mkefd0;1 z{Hs%BA>=>2`3qP9|Fl&46c9|diiG%}@kFwXUL;xp`ke_OQ3)mlQ#@`T{ol{i-`RtG z5B`kvZ$9q(diFw*AyZZ8oi4TGb|oR9k{EY8u16lVbV?9WFM;X=9^j3GL;9isg<-vsR>zG! zq3}>CUK4mbhi8uhe9o*nAEJ?zQ|}BL4qSC5+=oU}p0hu0d9nRbvB5g~E^kc7hJNsR zu#<7lN@$1$)3ea}t;IVN&?3$PB4y5&j@6%4U_UzlufZVY@_&{PxIyzc%wTc63)u}f zrQocvc6VU8$$>oe9A@OVJPpSJ#9u)eR`ce)j}o95M6QSfj)4M3kY@QY0_h0eA09`*tCOi*arF~02n-HEL17RC0tSOwN&tT4 zqOT{`0RREQ5CF(u7Z8O+!jV7+;9oNGiATPG_@6QvB#Hz~|6PWXMUYPKf6C-YQTw}0 z20}{LKV(SKUi+t>%pdbYAgDj|AaFQo_x-&uR1WrMUl@c`O#Z0{`C~j8D7gy#T~7us z`!9VFf6ReGB1jAU_r547384R{3@-OaU!)BAVElVu@|yiqhLS=3;V)A5Pg`VAG1d5|EB?CoIjSd=A@cVAdu5^zYOme`u#NBKaahLXiwsPddSGgKmj5m8v2@m F{{d=bm-7Gs literal 0 HcmV?d00001 diff --git a/figures/algoDelta/algoDelta_elapsedTime.pdf b/figures/algoDelta/algoDelta_elapsedTime.pdf new file mode 100644 index 0000000000000000000000000000000000000000..1892bda3bd8f439f2cd2b926bd10054737abdd5a GIT binary patch literal 8710 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 JS2xfA{XbkBT{-{& literal 0 HcmV?d00001 diff --git a/figures/algoDelta/algoDelta_froError.pdf b/figures/algoDelta/algoDelta_froError.pdf new file mode 100644 index 0000000000000000000000000000000000000000..c971b4c66ad8dab333cdc2765ac0665d284ac0ab GIT binary patch literal 8344 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