From 76d76f13cfc115a524a52d2d6989884c85490db8 Mon Sep 17 00:00:00 2001 From: Yasushi Negishi Date: Tue, 30 Apr 2024 07:18:30 +0000 Subject: [PATCH 1/8] Add a to generate a time chart figure from outputs generated module compiled by onnx-mlir with the "--InstrumentReportTime" option. Signed-off-by: Yasushi Negishi --- utils/make-timechart.py | 300 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 300 insertions(+) create mode 100755 utils/make-timechart.py diff --git a/utils/make-timechart.py b/utils/make-timechart.py new file mode 100755 index 0000000000..b337a73dbd --- /dev/null +++ b/utils/make-timechart.py @@ -0,0 +1,300 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: Apache-2.0 + +##################### make-timechart.py ####################################### +# +# Copyright 2019-2023 The IBM Research Authors. +# +################################################################################ +# +# Generate a timechart graph from an intstrumentation file. +# +################################################################################ +import matplotlib + +matplotlib.use("Agg") +import matplotlib.pyplot as plt +from matplotlib.legend_handler import HandlerTuple +import numpy as np +import argparse +import sys + +default_xscale = -1.0 # auto scale +default_xscales = [0.01, 0.02, 0.05, 0.10, 0.20, 0.25, 0.50, 1.0, 2.0, 2.5, 5.0, 10.0] +default_number_of_lines = -1 # auto scale +max_number_of_lines = 20 +default_start_time = 0.0 +default_period = 200.0 +max_number_of_legend = 18 +number_of_xticks = 5 + +elapsed_time_min = -1.0 +elapsed_time_max = -1.0 +epsilon = 1.0e-10 + +op_time_dic = {} +op_count_dic = {} +op_index_dic = {} +op_tbl = [] +time_tbl = [] +label_tbl = [] +colormap_tbl = [] +handle_tbl = [] + + +# Read instrumentation file +def read_inst_file(inst_file, iteration, data_start_time, data_period): + global elapsed_time_min, elapsed_time_max + data_end_time = data_start_time + data_period + inst_data_tbl = [] + before_elapsed_time_dic = {} + curr_iteration = 0 + with open(inst_file) as f: + for line in f: + columns = line.split(",") + first_column = columns[0].strip() + if first_column == "==START-REPORT==": + if iteration > curr_iteration: + break + if iteration < curr_iteration: + op_time_dic.clear() + op_count_dic.clear() + before_elapsed_time_dic.clear() + inst_data_tbl.clear() + elapsed_time_min = -1.0 + elapsed_time_max = -1.0 + curr_iteration += 1 + if first_column != "==PERF-REPORT==": + continue + if len(columns) != 6: + print("SKIP incomplete line [{}]".format(line), file=sys.stderr) + continue + op = columns[1].strip() + node = columns[2].strip() + before_after = columns[3].strip() + time = float(columns[4].strip()) + elapsed_time = float(columns[5].strip()) + if elapsed_time_min < -1.0: # reset + elapsed_time_min = elapsed_time + elapsed_time_max = elapsed_time + elapsed_time_max = max(elapsed_time_max, elapsed_time) + key = op + ":" + node + if before_after == "before": + before_elapsed_time_dic[key] = elapsed_time + if not op in op_time_dic: + op_time_dic[op] = 0.0 + op_count_dic[op] = 0 + continue + # before_after == "after" + if ( + key in before_elapsed_time_dic + and before_elapsed_time_dic[key] <= data_end_time + and elapsed_time >= data_start_time + ): + inst_data_tbl.append((key, before_elapsed_time_dic[key], elapsed_time)) + op_time_dic[op] += elapsed_time - before_elapsed_time_dic[key] + op_count_dic[op] += 1 + # else: + # print("WARNING: no corresponding line for [{}]".format(line), file=sys.stderr) + return inst_data_tbl + + +def write_line_for_op(op, start, end, ax, idx, xscale, number_of_lines): + line_height = number_of_lines * 0.02 + color = colormap_tbl[idx] + handle = None + while start + epsilon < end: + y, x = divmod(start + epsilon, xscale) + next_start = min(end, (y + 1) * xscale) + handle = ax.barh( + left=x, + y=number_of_lines - 1 - y, + width=next_start - start, + height=line_height, + align="center", + color=color, + label=op, + alpha=1.0, + linewidth=0.4, + ec="k", + ) + start = next_start + if handle: + handle_tbl[idx] = handle + return + + +def generate_timechart( + inst_data_tbl, + graph, + xscale, + number_of_lines, + data_start_time, + data_period, +): + data_end_time = data_start_time + data_period + frame_start_time = int(data_start_time / xscale) * xscale + fig, ax = plt.subplots() + plt.subplots_adjust(bottom=0.3, right=0.95) + # generate colormap + op_time_list = sorted(op_time_dic.items(), key=lambda x: x[1], reverse=True) + # color_table = plt.rcParams["axes.prop_cycle"].by_key()["color"] + total_time = sum(list(map(lambda x: x[1], op_time_list))) + for idx, op_time in enumerate(op_time_list): + op, time = op_time + op_index_dic[op] = idx + op_tbl.append(op) + time_tbl.append(time) + # colormap_tbl.append(color_table[idx % len(color_table)]) + colormap_tbl.append(matplotlib.cm.tab20(idx % 20)) + handle_tbl.append(None) + label_tbl.append( + "{}: {:.3f}s / {}".format(op[:13], op_time_dic[op], op_count_dic[op]) + ) + if args.print_summary: + print("{} {:.6f} {}".format(op, op_time_dic[op], op_count_dic[op])) + # plot inst_data + used_op_idx_list = [] + for inst_data in inst_data_tbl: + key, start, end = inst_data + start = max(start, data_start_time) - frame_start_time + end = min(end, data_end_time) - frame_start_time + op = key[: key.find(":")] + idx = op_index_dic[op] + write_line_for_op(op, start, end, ax, idx, xscale, number_of_lines) + + # ax.set_xlabel("Elapsed Time (sec)") + ax.set_xlim(0.0, xscale) + ax.xaxis.set_major_formatter("{x:+.3f}") + yticks = range(number_of_lines) + yticks_labels = list( + map( + lambda x: "{:.02f}".format( + frame_start_time + (number_of_lines - 1 - x) * xscale + ), + yticks, + ) + ) + ax.set_yticks(yticks) + ax.set_yticklabels(yticks_labels) + ax.set_ylim(-0.7, number_of_lines) + ax.set_ylabel("Elapsed Time (sec)") + title = args.title if args.title else "Time Chart [{}]".format(args.instrumentation) + ax.set_title(title) + handles = [] + labels = [] + for idx, hdl in enumerate(handle_tbl): + if hdl: + handles.append(handle_tbl[idx]) + labels.append(label_tbl[idx]) + ax.legend( + handles=handles[:max_number_of_legend], + labels=labels[:max_number_of_legend], + handler_map={tuple: HandlerTuple(ndivide=None)}, + frameon=False, + loc="lower center", + fontsize="x-small", + ncol=3, + bbox_to_anchor=(0.5, -0.5), + ) + # handler_map={tuple: HandlerTuple(ndivide=None)}, ncol=1, colmnspacing=1 + plt.grid(True) + plt.savefig(graph) + + +parser = argparse.ArgumentParser() +parser.add_argument( + "-i", + "--instrumentation", + type=str, + default="", + help="Path to instrumentation file to be read", +) +parser.add_argument( + "--print-summary", + action="store_true", + help="Flag to printout operation time summary (default=False)", +) +parser.add_argument( + "-g", + "--graph", + type=str, + default="", + help="Path to graph file to be generated", +) +parser.add_argument( + "-t", + "--title", + type=str, + default="", + help="Title of the graph", +) +parser.add_argument( + "--start-time", + type=float, + default=default_start_time, + help="Start time (sec) (default={})".format(default_start_time), +) +parser.add_argument( + "--period", + type=float, + default=default_period, + help="Period (sec) (default={})".format(default_period), +), +parser.add_argument( + "--xscale", + type=float, + default=default_xscale, + help="X-axis scale (default={})".format(default_xscale), +) +parser.add_argument( + "--number-of-lines", + type=int, + default=default_number_of_lines, + help="Number of timechart lines (default={})".format(default_number_of_lines), +) +parser.add_argument( + "--iteration", + type=int, + default=-1, + help="Iteration number starting from 0 (default=last)", +) + +args = parser.parse_args() +if not args.instrumentation: + print("error: no instrumentation file, use argument --inst") + print(parser.format_usage()) + exit(1) +if not args.graph: + print("error: no graph file, use argument --graph") + print(parser.format_usage()) + exit(1) + + +def main(): + inst_data_tbl = read_inst_file( + args.instrumentation, args.iteration, args.start_time, args.period + ) + xscale = args.xscale + if args.xscale < 0: # set xscale with auto scale + for scale in default_xscales: + if scale * max_number_of_lines >= elapsed_time_max: + break + xscale = scale + number_of_lines = args.number_of_lines + if number_of_lines < 0: # set number_of_lines with auto scale + number_of_lines = min( + int((elapsed_time_max + xscale - epsilon) / xscale), max_number_of_lines + ) + generate_timechart( + inst_data_tbl, + args.graph, + xscale, + number_of_lines, + args.start_time, + args.period, + ) + + +if __name__ == "__main__": + main() From 95cb12965d2a12b919fe88d7b66eaa62ef054558 Mon Sep 17 00:00:00 2001 From: Yasushi Negishi Date: Fri, 10 May 2024 09:19:53 +0000 Subject: [PATCH 2/8] Introducing "Other" in legend table. Signed-off-by: Yasushi Negishi --- utils/make-timechart.py | 137 ++++++++++++++++++++++++++++------------ 1 file changed, 96 insertions(+), 41 deletions(-) diff --git a/utils/make-timechart.py b/utils/make-timechart.py index b337a73dbd..e33c99ef89 100755 --- a/utils/make-timechart.py +++ b/utils/make-timechart.py @@ -25,11 +25,11 @@ max_number_of_lines = 20 default_start_time = 0.0 default_period = 200.0 +default_min_parcent_of_time_for_legend = 1.0 +min_number_of_legend = 10 max_number_of_legend = 18 -number_of_xticks = 5 -elapsed_time_min = -1.0 -elapsed_time_max = -1.0 +number_of_xticks = 5 epsilon = 1.0e-10 op_time_dic = {} @@ -44,7 +44,8 @@ # Read instrumentation file def read_inst_file(inst_file, iteration, data_start_time, data_period): - global elapsed_time_min, elapsed_time_max + elapsed_time_min = -1.0 + elapsed_time_max = -1.0 data_end_time = data_start_time + data_period inst_data_tbl = [] before_elapsed_time_dic = {} @@ -96,27 +97,79 @@ def read_inst_file(inst_file, iteration, data_start_time, data_period): op_count_dic[op] += 1 # else: # print("WARNING: no corresponding line for [{}]".format(line), file=sys.stderr) - return inst_data_tbl + return inst_data_tbl, elapsed_time_min, elapsed_time_max + + +def get_xscales_and_number_of_lines(elapsed_time_min, elapsed_time_max): + xscale = args.xscale + if xscale < 0: # set xscale with auto scale + for scale in default_xscales: + if scale * max_number_of_lines >= elapsed_time_max: + break + xscale = scale + number_of_lines = args.number_of_lines + if number_of_lines < 0: # set number_of_lines with auto scale + number_of_lines = min( + int((elapsed_time_max + xscale - epsilon) / xscale), max_number_of_lines + ) + return xscale, number_of_lines + + +def gen_legend_table(inst_data_tbl, number_of_legends): + op_time_list = sorted(op_time_dic.items(), key=lambda x: x[1], reverse=True) + total_time = sum(list(map(lambda x: x[1], op_time_list))) + legend_tbl = [] + other_time = 0.0 + other_count = 0 + color_tbl = plt.rcParams["axes.prop_cycle"].by_key()["color"] + for idx, op_time in enumerate(op_time_list): + op, time = op_time + op_index_dic[op] = min(idx, number_of_legends + 1) + if args.print_summary: + print("{} {:.6f} {}".format(op, op_time_dic[op], op_count_dic[op])) + if idx < number_of_legends: + fgcolor = color_tbl[idx] # matplotlib.cm.tab20(idx) + bgcolor = ( + "r" + if op.startswith("onnx.") + else "b" if op.startswith("zhigh.") else "k" + ) + label = "{}: {:.3f}s / {}".format( + op[:13], op_time_dic[op], op_count_dic[op] + ) + legend_tbl.append((op, time, fgcolor, bgcolor, label)) + else: + other_time += time + other_count += 1 + fgcolor = color_tbl[number_of_legends % len(color_tbl)] # matplotlib.cm.tab20(number_of_legends) + bgcolor = "k" + label = "{}: {:.3f}s / {}".format("Other", other_time, other_count) + legend_tbl.append(("Other", other_time, fgcolor, bgcolor, label)) + return legend_tbl -def write_line_for_op(op, start, end, ax, idx, xscale, number_of_lines): +def write_line_for_op( + op, start, end, ax, idx, legend_tbl, handle_tbl, xscale, number_of_lines +): line_height = number_of_lines * 0.02 - color = colormap_tbl[idx] + number_of_legend = len(legend_tbl) handle = None + idx = min(idx, number_of_legend - 1) while start + epsilon < end: y, x = divmod(start + epsilon, xscale) next_start = min(end, (y + 1) * xscale) + _, _, fgcolor, bgcolor, _ = legend_tbl[idx] handle = ax.barh( left=x, y=number_of_lines - 1 - y, width=next_start - start, height=line_height, align="center", - color=color, + color=fgcolor, label=op, alpha=1.0, - linewidth=0.4, - ec="k", + linewidth=1.0, + ec=bgcolor, ) start = next_start if handle: @@ -126,6 +179,7 @@ def write_line_for_op(op, start, end, ax, idx, xscale, number_of_lines): def generate_timechart( inst_data_tbl, + legend_tbl, graph, xscale, number_of_lines, @@ -136,32 +190,19 @@ def generate_timechart( frame_start_time = int(data_start_time / xscale) * xscale fig, ax = plt.subplots() plt.subplots_adjust(bottom=0.3, right=0.95) - # generate colormap - op_time_list = sorted(op_time_dic.items(), key=lambda x: x[1], reverse=True) - # color_table = plt.rcParams["axes.prop_cycle"].by_key()["color"] - total_time = sum(list(map(lambda x: x[1], op_time_list))) - for idx, op_time in enumerate(op_time_list): - op, time = op_time - op_index_dic[op] = idx - op_tbl.append(op) - time_tbl.append(time) - # colormap_tbl.append(color_table[idx % len(color_table)]) - colormap_tbl.append(matplotlib.cm.tab20(idx % 20)) - handle_tbl.append(None) - label_tbl.append( - "{}: {:.3f}s / {}".format(op[:13], op_time_dic[op], op_count_dic[op]) - ) - if args.print_summary: - print("{} {:.6f} {}".format(op, op_time_dic[op], op_count_dic[op])) + # plot inst_data used_op_idx_list = [] + handle_tbl = [None] * len(legend_tbl) for inst_data in inst_data_tbl: key, start, end = inst_data start = max(start, data_start_time) - frame_start_time end = min(end, data_end_time) - frame_start_time op = key[: key.find(":")] idx = op_index_dic[op] - write_line_for_op(op, start, end, ax, idx, xscale, number_of_lines) + write_line_for_op( + op, start, end, ax, idx, legend_tbl, handle_tbl, xscale, number_of_lines + ) # ax.set_xlabel("Elapsed Time (sec)") ax.set_xlim(0.0, xscale) @@ -186,7 +227,9 @@ def generate_timechart( for idx, hdl in enumerate(handle_tbl): if hdl: handles.append(handle_tbl[idx]) - labels.append(label_tbl[idx]) + _, _, _, _, label = legend_tbl[idx] + labels.append(label) + print("YYYY labels({}) = {}".format(len(labels), labels)) ax.legend( handles=handles[:max_number_of_legend], labels=labels[:max_number_of_legend], @@ -259,6 +302,18 @@ def generate_timechart( default=-1, help="Iteration number starting from 0 (default=last)", ) +parser.add_argument( + "-l", + "--number-of-legends", + type=int, + default=-1, + help="Number of legend. The default is number of operations occupying " + + "{} parcent of execution time (s.t. {} <= n <= {})".format( + default_min_parcent_of_time_for_legend, + min_number_of_legend, + max_number_of_legend, + ), +) args = parser.parse_args() if not args.instrumentation: @@ -272,22 +327,22 @@ def generate_timechart( def main(): - inst_data_tbl = read_inst_file( + # read instrumentation file + inst_data_tbl, elapsed_time_min, elapsed_time_max = read_inst_file( args.instrumentation, args.iteration, args.start_time, args.period ) - xscale = args.xscale - if args.xscale < 0: # set xscale with auto scale - for scale in default_xscales: - if scale * max_number_of_lines >= elapsed_time_max: - break - xscale = scale - number_of_lines = args.number_of_lines - if number_of_lines < 0: # set number_of_lines with auto scale - number_of_lines = min( - int((elapsed_time_max + xscale - epsilon) / xscale), max_number_of_lines - ) + # set xscale and number_of_lines + xscale, number_of_lines = get_xscales_and_number_of_lines( + elapsed_time_min, elapsed_time_max + ) + # generate legend table + number_of_legends = 10 + legend_tbl = gen_legend_table(inst_data_tbl, number_of_legends) + print("XXXX legend_tbl({}) = {}".format(len(legend_tbl), legend_tbl)) + # generate timechart generate_timechart( inst_data_tbl, + legend_tbl, args.graph, xscale, number_of_lines, From dd5a58fe26475100448b307cc625882122d3d635 Mon Sep 17 00:00:00 2001 From: Yasushi Negishi Date: Mon, 13 May 2024 05:16:51 +0000 Subject: [PATCH 3/8] Introduce "Other" in legend. Signed-off-by: Yasushi Negishi --- utils/make-timechart.py | 61 +++++++++++++++++++++++++++++++---------- 1 file changed, 46 insertions(+), 15 deletions(-) diff --git a/utils/make-timechart.py b/utils/make-timechart.py index e33c99ef89..223ede4626 100755 --- a/utils/make-timechart.py +++ b/utils/make-timechart.py @@ -3,7 +3,7 @@ ##################### make-timechart.py ####################################### # -# Copyright 2019-2023 The IBM Research Authors. +# Copyright 2019-2024 The IBM Research Authors. # ################################################################################ # @@ -20,13 +20,26 @@ import sys default_xscale = -1.0 # auto scale -default_xscales = [0.01, 0.02, 0.05, 0.10, 0.20, 0.25, 0.50, 1.0, 2.0, 2.5, 5.0, 10.0] +default_xscales = [ + 0.01, + 0.02, + 0.025, + 0.05, + 0.10, + 0.20, + 0.25, + 0.50, + 1.0, + 2.0, + 2.5, + 5.0, + 10.0, +] default_number_of_lines = -1 # auto scale max_number_of_lines = 20 default_start_time = 0.0 default_period = 200.0 default_min_parcent_of_time_for_legend = 1.0 -min_number_of_legend = 10 max_number_of_legend = 18 number_of_xticks = 5 @@ -115,9 +128,17 @@ def get_xscales_and_number_of_lines(elapsed_time_min, elapsed_time_max): return xscale, number_of_lines -def gen_legend_table(inst_data_tbl, number_of_legends): +def gen_legend_table(inst_data_tbl, minimum_legend_parcent, number_of_legends): op_time_list = sorted(op_time_dic.items(), key=lambda x: x[1], reverse=True) total_time = sum(list(map(lambda x: x[1], op_time_list))) + # calculate number_of_legend + if number_of_legends < 0: + for idx, op_time in enumerate(op_time_list): + op, time = op_time + if time < total_time * (minimum_legend_parcent / 100.0): + break + number_of_legends = idx + number_of_legends = min(max_number_of_legend, number_of_legends) legend_tbl = [] other_time = 0.0 other_count = 0 @@ -128,7 +149,7 @@ def gen_legend_table(inst_data_tbl, number_of_legends): if args.print_summary: print("{} {:.6f} {}".format(op, op_time_dic[op], op_count_dic[op])) if idx < number_of_legends: - fgcolor = color_tbl[idx] # matplotlib.cm.tab20(idx) + fgcolor = color_tbl[idx] # matplotlib.cm.tab20(idx) bgcolor = ( "r" if op.startswith("onnx.") @@ -141,8 +162,11 @@ def gen_legend_table(inst_data_tbl, number_of_legends): else: other_time += time other_count += 1 - fgcolor = color_tbl[number_of_legends % len(color_tbl)] # matplotlib.cm.tab20(number_of_legends) - bgcolor = "k" + # prepare legend for "other" + fgcolor = color_tbl[ + number_of_legends % len(color_tbl) + ] # matplotlib.cm.tab20(number_of_legends) + bgcolor = "y" label = "{}: {:.3f}s / {}".format("Other", other_time, other_count) legend_tbl.append(("Other", other_time, fgcolor, bgcolor, label)) return legend_tbl @@ -151,7 +175,7 @@ def gen_legend_table(inst_data_tbl, number_of_legends): def write_line_for_op( op, start, end, ax, idx, legend_tbl, handle_tbl, xscale, number_of_lines ): - line_height = number_of_lines * 0.02 + line_height = 9.0 / number_of_lines number_of_legend = len(legend_tbl) handle = None idx = min(idx, number_of_legend - 1) @@ -168,7 +192,7 @@ def write_line_for_op( color=fgcolor, label=op, alpha=1.0, - linewidth=1.0, + linewidth=0.8, ec=bgcolor, ) start = next_start @@ -229,7 +253,6 @@ def generate_timechart( handles.append(handle_tbl[idx]) _, _, _, _, label = legend_tbl[idx] labels.append(label) - print("YYYY labels({}) = {}".format(len(labels), labels)) ax.legend( handles=handles[:max_number_of_legend], labels=labels[:max_number_of_legend], @@ -302,15 +325,23 @@ def generate_timechart( default=-1, help="Iteration number starting from 0 (default=last)", ) +parser.add_argument( + "--minimum-legend-parcent", + type=int, + default=default_min_parcent_of_time_for_legend, + help="Minimum execution time of each operation to have a legend in parcent" + + "(default={}). This opion cannot be used with --number-of-legends option".format( + default_min_parcent_of_time_for_legend + ), +) parser.add_argument( "-l", "--number-of-legends", type=int, default=-1, help="Number of legend. The default is number of operations occupying " - + "{} parcent of execution time (s.t. {} <= n <= {})".format( + + "{} parcent of execution time (s.t. n <= {})".format( default_min_parcent_of_time_for_legend, - min_number_of_legend, max_number_of_legend, ), ) @@ -336,9 +367,9 @@ def main(): elapsed_time_min, elapsed_time_max ) # generate legend table - number_of_legends = 10 - legend_tbl = gen_legend_table(inst_data_tbl, number_of_legends) - print("XXXX legend_tbl({}) = {}".format(len(legend_tbl), legend_tbl)) + legend_tbl = gen_legend_table( + inst_data_tbl, args.minimum_legend_parcent, args.number_of_legends + ) # generate timechart generate_timechart( inst_data_tbl, From a95ff9f0a03ebc3d0f20a799268140d689655621 Mon Sep 17 00:00:00 2001 From: Yasushi Negishi Date: Mon, 13 May 2024 06:48:12 +0000 Subject: [PATCH 4/8] Fix positions of generated graphs. Signed-off-by: Yasushi Negishi --- utils/make-timechart.py | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/utils/make-timechart.py b/utils/make-timechart.py index 223ede4626..b2abd06682 100755 --- a/utils/make-timechart.py +++ b/utils/make-timechart.py @@ -18,6 +18,7 @@ import numpy as np import argparse import sys +import os default_xscale = -1.0 # auto scale default_xscales = [ @@ -40,11 +41,15 @@ default_start_time = 0.0 default_period = 200.0 default_min_parcent_of_time_for_legend = 1.0 -max_number_of_legend = 18 +max_number_of_legend = 11 number_of_xticks = 5 epsilon = 1.0e-10 +# color table definition +#color_map = plt.rcParams["axes.prop_cycle"].by_key()["color"] # 10 colors +color_map = matplotlib.cm.tab20.colors # 20 colors + op_time_dic = {} op_count_dic = {} op_index_dic = {} @@ -142,14 +147,13 @@ def gen_legend_table(inst_data_tbl, minimum_legend_parcent, number_of_legends): legend_tbl = [] other_time = 0.0 other_count = 0 - color_tbl = plt.rcParams["axes.prop_cycle"].by_key()["color"] for idx, op_time in enumerate(op_time_list): op, time = op_time op_index_dic[op] = min(idx, number_of_legends + 1) if args.print_summary: print("{} {:.6f} {}".format(op, op_time_dic[op], op_count_dic[op])) if idx < number_of_legends: - fgcolor = color_tbl[idx] # matplotlib.cm.tab20(idx) + fgcolor = color_map[idx % len(color_map)] # matplotlib.cm.tab20(idx) bgcolor = ( "r" if op.startswith("onnx.") @@ -163,8 +167,8 @@ def gen_legend_table(inst_data_tbl, minimum_legend_parcent, number_of_legends): other_time += time other_count += 1 # prepare legend for "other" - fgcolor = color_tbl[ - number_of_legends % len(color_tbl) + fgcolor = color_map[ + number_of_legends % len(color_map) ] # matplotlib.cm.tab20(number_of_legends) bgcolor = "y" label = "{}: {:.3f}s / {}".format("Other", other_time, other_count) @@ -213,7 +217,7 @@ def generate_timechart( data_end_time = data_start_time + data_period frame_start_time = int(data_start_time / xscale) * xscale fig, ax = plt.subplots() - plt.subplots_adjust(bottom=0.3, right=0.95) + plt.subplots_adjust(bottom=0.25, right=0.93) # plot inst_data used_op_idx_list = [] @@ -254,14 +258,14 @@ def generate_timechart( _, _, _, _, label = legend_tbl[idx] labels.append(label) ax.legend( - handles=handles[:max_number_of_legend], - labels=labels[:max_number_of_legend], + handles=handles[:len(legend_tbl)], + labels=labels[:len(legend_tbl)], handler_map={tuple: HandlerTuple(ndivide=None)}, frameon=False, loc="lower center", fontsize="x-small", ncol=3, - bbox_to_anchor=(0.5, -0.5), + bbox_to_anchor=(0.5, -0.3), ) # handler_map={tuple: HandlerTuple(ndivide=None)}, ncol=1, colmnspacing=1 plt.grid(True) @@ -270,9 +274,7 @@ def generate_timechart( parser = argparse.ArgumentParser() parser.add_argument( - "-i", - "--instrumentation", - type=str, + "instrumentation", default="", help="Path to instrumentation file to be read", ) @@ -327,7 +329,7 @@ def generate_timechart( ) parser.add_argument( "--minimum-legend-parcent", - type=int, + type=float, default=default_min_parcent_of_time_for_legend, help="Minimum execution time of each operation to have a legend in parcent" + "(default={}). This opion cannot be used with --number-of-legends option".format( @@ -351,10 +353,6 @@ def generate_timechart( print("error: no instrumentation file, use argument --inst") print(parser.format_usage()) exit(1) -if not args.graph: - print("error: no graph file, use argument --graph") - print(parser.format_usage()) - exit(1) def main(): @@ -374,7 +372,7 @@ def main(): generate_timechart( inst_data_tbl, legend_tbl, - args.graph, + args.graph if args.graph else os.path.splitext(args.instrumentation)[0] + ".png", xscale, number_of_lines, args.start_time, From 300f4c91fa0c37830f746f7aa37cc7da0fde95ec Mon Sep 17 00:00:00 2001 From: Yasushi Negishi Date: Mon, 13 May 2024 06:50:41 +0000 Subject: [PATCH 5/8] Fix python code format issues. Signed-off-by: Yasushi Negishi --- utils/make-timechart.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/utils/make-timechart.py b/utils/make-timechart.py index b2abd06682..93d17fd0ea 100755 --- a/utils/make-timechart.py +++ b/utils/make-timechart.py @@ -47,8 +47,8 @@ epsilon = 1.0e-10 # color table definition -#color_map = plt.rcParams["axes.prop_cycle"].by_key()["color"] # 10 colors -color_map = matplotlib.cm.tab20.colors # 20 colors +# color_map = plt.rcParams["axes.prop_cycle"].by_key()["color"] # 10 colors +color_map = matplotlib.cm.tab20.colors # 20 colors op_time_dic = {} op_count_dic = {} @@ -153,7 +153,7 @@ def gen_legend_table(inst_data_tbl, minimum_legend_parcent, number_of_legends): if args.print_summary: print("{} {:.6f} {}".format(op, op_time_dic[op], op_count_dic[op])) if idx < number_of_legends: - fgcolor = color_map[idx % len(color_map)] # matplotlib.cm.tab20(idx) + fgcolor = color_map[idx % len(color_map)] # matplotlib.cm.tab20(idx) bgcolor = ( "r" if op.startswith("onnx.") @@ -258,8 +258,8 @@ def generate_timechart( _, _, _, _, label = legend_tbl[idx] labels.append(label) ax.legend( - handles=handles[:len(legend_tbl)], - labels=labels[:len(legend_tbl)], + handles=handles[: len(legend_tbl)], + labels=labels[: len(legend_tbl)], handler_map={tuple: HandlerTuple(ndivide=None)}, frameon=False, loc="lower center", @@ -372,7 +372,11 @@ def main(): generate_timechart( inst_data_tbl, legend_tbl, - args.graph if args.graph else os.path.splitext(args.instrumentation)[0] + ".png", + ( + args.graph + if args.graph + else os.path.splitext(args.instrumentation)[0] + ".png" + ), xscale, number_of_lines, args.start_time, From 94c9bca565c2cd5a61df3cb35fc0f2d744819628 Mon Sep 17 00:00:00 2001 From: Yasushi Negishi Date: Tue, 14 May 2024 07:25:32 +0000 Subject: [PATCH 6/8] Fix typos. Signed-off-by: Yasushi Negishi --- utils/make-timechart.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/utils/make-timechart.py b/utils/make-timechart.py index 93d17fd0ea..43d2d78429 100755 --- a/utils/make-timechart.py +++ b/utils/make-timechart.py @@ -40,7 +40,7 @@ max_number_of_lines = 20 default_start_time = 0.0 default_period = 200.0 -default_min_parcent_of_time_for_legend = 1.0 +default_min_percent_of_time_for_legend = 1.0 max_number_of_legend = 11 number_of_xticks = 5 @@ -133,14 +133,14 @@ def get_xscales_and_number_of_lines(elapsed_time_min, elapsed_time_max): return xscale, number_of_lines -def gen_legend_table(inst_data_tbl, minimum_legend_parcent, number_of_legends): +def gen_legend_table(inst_data_tbl, minimum_legend_percent, number_of_legends): op_time_list = sorted(op_time_dic.items(), key=lambda x: x[1], reverse=True) total_time = sum(list(map(lambda x: x[1], op_time_list))) # calculate number_of_legend if number_of_legends < 0: for idx, op_time in enumerate(op_time_list): op, time = op_time - if time < total_time * (minimum_legend_parcent / 100.0): + if time < total_time * (minimum_legend_percent / 100.0): break number_of_legends = idx number_of_legends = min(max_number_of_legend, number_of_legends) @@ -328,12 +328,12 @@ def generate_timechart( help="Iteration number starting from 0 (default=last)", ) parser.add_argument( - "--minimum-legend-parcent", + "--minimum-legend-percent", type=float, - default=default_min_parcent_of_time_for_legend, - help="Minimum execution time of each operation to have a legend in parcent" - + "(default={}). This opion cannot be used with --number-of-legends option".format( - default_min_parcent_of_time_for_legend + default=default_min_percent_of_time_for_legend, + help="Minimum execution time of each operation to have a legend in percent" + + "(default={}). This option cannot be used with --number-of-legends option".format( + default_min_percent_of_time_for_legend ), ) parser.add_argument( @@ -342,8 +342,8 @@ def generate_timechart( type=int, default=-1, help="Number of legend. The default is number of operations occupying " - + "{} parcent of execution time (s.t. n <= {})".format( - default_min_parcent_of_time_for_legend, + + "{} percent of execution time (s.t. n <= {})".format( + default_min_percent_of_time_for_legend, max_number_of_legend, ), ) @@ -366,7 +366,7 @@ def main(): ) # generate legend table legend_tbl = gen_legend_table( - inst_data_tbl, args.minimum_legend_parcent, args.number_of_legends + inst_data_tbl, args.minimum_legend_percent, args.number_of_legends ) # generate timechart generate_timechart( From fb797ef6b6e89f5086b57e0060ce6c6647430f66 Mon Sep 17 00:00:00 2001 From: Yasushi Negishi Date: Fri, 31 May 2024 06:44:53 +0000 Subject: [PATCH 7/8] Support to ignore the "Total" op Signed-off-by: Yasushi Negishi --- utils/make-timechart.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/utils/make-timechart.py b/utils/make-timechart.py index 43d2d78429..cd44ed4b8f 100755 --- a/utils/make-timechart.py +++ b/utils/make-timechart.py @@ -89,6 +89,8 @@ def read_inst_file(inst_file, iteration, data_start_time, data_period): print("SKIP incomplete line [{}]".format(line), file=sys.stderr) continue op = columns[1].strip() + if op == 'Total': + continue node = columns[2].strip() before_after = columns[3].strip() time = float(columns[4].strip()) From 5435e5e497d9f5c14a8562b017c68512321de84c Mon Sep 17 00:00:00 2001 From: Yasushi Negishi Date: Fri, 31 May 2024 07:00:04 +0000 Subject: [PATCH 8/8] Fix python format errors. Signed-off-by: Yasushi Negishi --- utils/make-timechart.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/make-timechart.py b/utils/make-timechart.py index cd44ed4b8f..abe454a27a 100755 --- a/utils/make-timechart.py +++ b/utils/make-timechart.py @@ -89,7 +89,7 @@ def read_inst_file(inst_file, iteration, data_start_time, data_period): print("SKIP incomplete line [{}]".format(line), file=sys.stderr) continue op = columns[1].strip() - if op == 'Total': + if op == "Total": continue node = columns[2].strip() before_after = columns[3].strip()