diff --git a/analysis/data_stat.py b/analysis/data_stat.py index c1ee542..dace377 100644 --- a/analysis/data_stat.py +++ b/analysis/data_stat.py @@ -3,37 +3,37 @@ import re from enum import Enum class Stat(Enum): - CPU = 'cpu' + CPU = 'CPU' - CORES = 'cores' - ITERATIONS = 'iterations' - BASELINE_TIME_S = 'baseline time (sec)' - BASELINE_DELAY_S = 'baseline delay (sec)' + CORES = 'Cores' + ITERATIONS = 'Iterations' + BASELINE_TIME_S = 'Baseline Time (sec)' + BASELINE_DELAY_S = 'Baseline Delay (sec)' - SOLVER = 'solver' + SOLVER = 'Solver' - MATRIX_TYPE = 'matrix type' - MATRIX_FILE = 'matrix file' - MATRIX_FORMAT = 'matrix format' - MATRIX_SHAPE = 'matrix shape' - MATRIX_ROWS = 'matrix rows' - MATRIX_SIZE = 'matrix size' - MATRIX_NNZ = 'matrix nnz' - MATRIX_DENSITY = 'matrix density' + MATRIX_TYPE = 'Matrix Type' + MATRIX_FILE = 'Matrix File' + MATRIX_FORMAT = 'Format' + MATRIX_SHAPE = 'Matrix Shape' + MATRIX_ROWS = 'Rows' + MATRIX_SIZE = 'Matrix Size' + MATRIX_NNZ = 'Number of Non-Zeros' + MATRIX_DENSITY = 'Density' #POWER_BEFORE = 'power before' #POWER = 'power' #POWER_AFTER = 'power after' - TIME_S = 'time (sec)' - TIME_S_1KI = 'time (sec) per 1k iterations' - J = 'joules' - J_1KI = 'joules per 1k iterations' - J_D = 'Δ joules' - J_D_1KI = 'Δ joules per 1k iterations' - W = 'watts' - W_1KI = 'watts per 1k iterations' - W_D = 'Δ watts' - W_D_1KI = 'Δ watts per 1k iterations' + TIME_S = 'Time (s)' + TIME_S_1KI = 'Time (s) per 1k Iterations' + J = 'Joules' + J_1KI = 'Joules per 1k iterations' + J_D = 'Δ Joules' + J_D_1KI = 'Δ Joules per 1k iterations' + W = 'Watts' + W_1KI = 'Watts per 1k iterations' + W_D = 'Δ Watts' + W_D_1KI = 'Δ Watts per 1k iterations' #DELTA_WATT = 'Δ watt' TASK_CLK = 'task clock (msec)' diff --git a/pytorch/analyze.py b/pytorch/analyze.py index d023bfa..2fbc036 100755 --- a/pytorch/analyze.py +++ b/pytorch/analyze.py @@ -19,15 +19,32 @@ class Plot(Enum): BOX = 'box' LINE = 'line' -def accumulate(data_list: list[dict[str, str | int | float]], category: Stat, value: Stat): - #print(category.name) - #print(value.name) - category_list = np.array([stats[category.name] for stats in data_list if value.name in stats]) +def accumulate( + data_list: list[dict[str, str | int | float]], + category: Stat, + category2: Stat, + value: Stat +) -> dict[np.ndarray]: + result: dict[np.ndarray] = dict() + value_list = np.array([stats[value.name] for stats in data_list if value.name in stats]) - result: dict[np.ndarray] = dict() - for category in np.sort(np.unique(category_list)): - result[category] = value_list[category_list == category] + if category2 is None: + category_list = np.array([(stats[category.name]) + for stats in data_list if value.name in stats]) + + for category in np.unique(category_list): + result[category] = value_list[category_list == category] + else: + category_list = np.array([(stats[category.name], + stats[category2.name]) + for stats in data_list if value.name in stats], dtype='object') + + for category in category_list: + mask = np.logical_and(category_list[:, 0] == category[0], category_list[:, 1] == category[1]) + assert (tuple(category) not in result.keys() + or np.array_equal(result[tuple(category)], value_list[mask])) + result[tuple(category)] = value_list[mask] return result @@ -41,25 +58,58 @@ def box_plot(ax, data_list: list[dict[str, str | int | float]], x: Stat, y: Stat def line_plot( ax, data_list: list[dict[str, str | int | float]], - x: Stat, y: Stat, color: Stat, - font_size: int + x: Stat, y: Stat, color: Stat, linestyle: Stat ): - print(x) - print(y) - print(color) - x_data: dict[str, np.ndarray] = accumulate(data_list, color, x) - y_data: dict[str, np.ndarray] = accumulate(data_list, color, y) + x_data: dict[str, np.ndarray] = accumulate(data_list, color, linestyle, x) + y_data: dict[str, np.ndarray] = accumulate(data_list, color, linestyle, y) - for category in x_data.keys(): + linestyle_tuple = [ + ('solid', (0, ())), + #('loosely dotted', (0, (1, 10))), + ('dotted', (0, (1, 1))), + #('densely dotted', (0, (1, 1))), + ('long dash with offset', (5, (10, 3))), + ('loosely dashed', (0, (5, 10))), + ('dashed', (0, (5, 5))), + ('densely dashed', (0, (5, 1))), + + ('loosely dashdotted', (0, (3, 10, 1, 10))), + ('dashdotted', (0, (3, 5, 1, 5))), + ('densely dashdotted', (0, (3, 1, 1, 1))), + + ('dashdotdotted', (0, (3, 5, 1, 5, 1, 5))), + ('loosely dashdotdotted', (0, (3, 10, 1, 10, 1, 10))), + ('densely dashdotdotted', (0, (3, 1, 1, 1, 1, 1)))] + + if linestyle is None: + color_mapping = dict(zip( + sorted({color for color in x_data.keys()}), + matplotlib.colors.BASE_COLORS.values())) + else: + color_mapping = dict(zip( + sorted({color for (color, _) in x_data.keys()}), + matplotlib.colors.BASE_COLORS.values())) + linestyle_mapping = dict(zip( + sorted({linestyle for (_, linestyle) in x_data.keys()}), + [linestyle for (_, linestyle) in linestyle_tuple])) + for category in sorted(x_data.keys()): sorted_indices = np.argsort(x_data[category]) x_data[category] = x_data[category][sorted_indices] y_data[category] = y_data[category][sorted_indices] - ax.plot(x_data[category], y_data[category], label=category) + if linestyle is None: + ax.plot(x_data[category], y_data[category], label=str(category), marker='o') + else: + ax.plot(x_data[category], y_data[category], label=str(category[0]) + ", " + str(category[1]), + color=color_mapping[category[0]], + linestyle=linestyle_mapping[category[1]], + marker='o') #print("Plotted x data: " + str(x_data[category])) #print("Plotted y data: " + str(y_data[category])) + #for category, (_, linestyle) in zip(sorted(x_data.keys()), linestyle_tuple): + #ax.plot(x_data[category], y_data[category], label=category, marker='o', linestyle=linestyle) - ax.set_ylabel(y.value, fontsize=font_size) - ax.grid(True) + #ax.set_yscale('log') + #ax.set_xscale('log') def visualize( data_list: list[dict[str, str | int | float]], @@ -70,6 +120,9 @@ def visualize( x: Stat, ys: list[Stat], color: Stat, + linestyle: Stat, + x_log: bool, + y_log: bool, filter_list: list[str], title: str ): @@ -98,22 +151,32 @@ def visualize( print(int(math.ceil(len(ys) / rows))) fig, axes = plt.subplots(rows, int(math.ceil(len(ys) / rows)), figsize = (16 * size_multiplier, 9 * size_multiplier)) + print(len(axes)) match plot: case Plot.BOX: for i, y in enumerate(ys): - box_plot(axes[i % rows][int(i / rows)], data_list, x, y) + ax = axes[i % rows][int(i / rows)] + box_plot(ax, data_list, x, y) case Plot.LINE: for i, y in enumerate(ys): - ax = axes[i % rows][int(i / rows)] - line_plot(ax, data_list, x, y, color, font_size) + ax = axes[i % rows] + if len(ys) > len(axes): + ax = ax[int(i / rows)] + line_plot(ax, data_list, x, y, color, linestyle) + + ax.set_ylabel(y.value, fontsize=font_size) + ax.grid(True) + if x_log: + ax.set_xscale('log') + if y_log: + ax.set_yscale('log') if type(ax.get_xaxis().get_major_formatter()) is matplotlib.ticker.ScalarFormatter: ax.get_xaxis().get_major_formatter().set_scientific(False) if type(ax.get_yaxis().get_major_formatter()) is matplotlib.ticker.ScalarFormatter: ax.get_yaxis().get_major_formatter().set_scientific(False) - #ax.ticklabel_format(axis='both', style='plain') - handles, labels = axes[i % rows][int(i / rows)].get_legend_handles_labels() + handles, labels = ax.get_legend_handles_labels() # else: # fig, ax = plt.subplots() # @@ -135,8 +198,12 @@ def visualize( # #title = f"{plot.value}_plot_of_{y.replace(' ', '_')}_vs_{x.replace(' ', '_')}_by_{color.replace(' ', '_')}_excluding_{filter_list}" # title = "altra_spmv" #title = f'{plot.value} plot of {[y.value for y in ys]} vs {x.value} by {color.value} excluding {filter_list}' - #fig.suptitle(title, fontsize = font_size) - fig.legend(handles, labels, fontsize = font_size) + fig.suptitle(title, fontsize = font_size) + fig.legend(handles, labels, + title=color.value if linestyle is None + else color.value + ", " + linestyle.value, + title_fontsize=font_size, + fontsize = font_size) fig.supxlabel(x.value, fontsize = font_size) #title = f'{plot.value} plot of {[y.name for y in ys]} vs {x.name} by {color.name} excluding {filter_list}' @@ -175,6 +242,13 @@ def main(): parser.add_argument('-c', '--color', choices=[c.name.lower() for c in Stat], help = 'the name of the color') + parser.add_argument('-l', '--linestyle', + choices=[l.name.lower() for l in Stat], + help = 'the name of the marker') + parser.add_argument('--x_log', action='store_true', + help = 'set x axis scale to log') + parser.add_argument('--y_log', action='store_true', + help = 'set y axis scale to log') parser.add_argument('-f', '--filter', nargs = '+', help = 'a comma-separated string of names and values to filter out.', default = []) @@ -184,6 +258,7 @@ def main(): args.ys = ([Stat[y.upper()] for y in args.ys] if args.ys is not None else None) args.color = Stat[args.color.upper()] if args.color is not None else None + args.linestyle = Stat[args.linestyle.upper()] if args.linestyle is not None else None data_list: list[dict] = list() @@ -202,6 +277,9 @@ def main(): args.x, args.ys, args.color, + args.linestyle, + args.x_log, + args.y_log, args.filter, args.title )