[llvm] 402f91b - [llvm-mca] Plot as result of comparing multiple files
Djordje Todorovic via llvm-commits
llvm-commits at lists.llvm.org
Fri Jan 28 04:05:44 PST 2022
Author: Milica Matic
Date: 2022-01-28T13:04:52+01:00
New Revision: 402f91bcbb5157a122b92366b0f5f9a917df06a3
URL: https://github.com/llvm/llvm-project/commit/402f91bcbb5157a122b92366b0f5f9a917df06a3
DIFF: https://github.com/llvm/llvm-project/commit/402f91bcbb5157a122b92366b0f5f9a917df06a3.diff
LOG: [llvm-mca] Plot as result of comparing multiple files
This patch introduces a new options for script llvm-mca-compare.py
(-plot-resource-pressure, -plot) to draw plots for llvm-mca tool
statistics and option (--plot-path) to specify relative path where
you want to save the plots.
Differential Revision: https://reviews.llvm.org/D115718
Added:
Modified:
llvm/utils/llvm-mca-compare.py
Removed:
################################################################################
diff --git a/llvm/utils/llvm-mca-compare.py b/llvm/utils/llvm-mca-compare.py
index 72c875d42442..ca69bc945af1 100755
--- a/llvm/utils/llvm-mca-compare.py
+++ b/llvm/utils/llvm-mca-compare.py
@@ -2,6 +2,7 @@
import argparse
import sys
+import os
from json import loads
from subprocess import Popen, PIPE
@@ -60,6 +61,27 @@ def parse_program_args(parser):
default=["-"],
help="Forward options to lvm-mca tool.",
)
+ parser.add_argument(
+ "-plot",
+ action="store_true",
+ default=False,
+ help="Draw plots of statistics for input files.",
+ )
+ parser.add_argument(
+ "-plot-resource-pressure",
+ action="store_true",
+ default=False,
+ help="Draw plots of resource pressure per iterations for input files.",
+ )
+ parser.add_argument(
+ "--plot-path",
+ nargs=1,
+ type=str,
+ action="store",
+ metavar="[=<path>]",
+ default=["-"],
+ help="Specify relative path where you want to save the plots.",
+ )
parser.add_argument(
"-v",
action="store_true",
@@ -69,6 +91,17 @@ def parse_program_args(parser):
return parser.parse_args()
+# Verify that the program inputs meet the requirements.
+def verify_program_inputs(opts):
+ if opts.plot_path[0] != "-" and not opts.plot and not opts.plot_resource_pressure:
+ print(
+ "error: Please specify --plot-path only with the -plot or -plot-resource-pressure options."
+ )
+ return False
+
+ return True
+
+
# Returns the name of the file to be analyzed from the path it is on.
def get_filename_from_path(path):
index_of_slash = path.rfind("/")
@@ -129,7 +162,7 @@ def run_llvm_mca_tool(opts, file_name):
"ResourcePressureInfo"
]
- name_target_info_resources = [" "] + json_parsed["TargetInfo"]["Resources"]
+ name_target_info_resources = json_parsed["TargetInfo"]["Resources"]
for s in range(len(resource_pressure_info)):
obj_of_resource_pressure_info = resource_pressure_info[s]
@@ -243,7 +276,9 @@ def console_print_results(matrix_of_code_regions, opts):
for j in range(len(matrix_of_code_regions) + 1)
]
- table_values[0] = matrix_of_code_regions[0][0].name_target_info_resources
+ table_values[0] = [" "] + matrix_of_code_regions[0][
+ 0
+ ].name_target_info_resources
for j in range(len(matrix_of_code_regions)):
if len(matrix_of_code_regions[j]) > i:
@@ -263,15 +298,289 @@ def console_print_results(matrix_of_code_regions, opts):
print("\n")
+# Based on the obtained results (summary view) of llvm-mca tool, draws plots for multiple input files.
+def draw_plot_files_summary(array_of_summary, opts):
+ try:
+ import matplotlib.pyplot as plt
+ except ImportError:
+ print("error: matplotlib.pyplot not found.")
+ sys.exit(1)
+ try:
+ from matplotlib.cm import get_cmap
+ except ImportError:
+ print("error: get_cmap (matplotlib.cm) not found.")
+ sys.exit(1)
+
+ names = [
+ "Block RThroughput",
+ "Dispatch Width",
+ "IPC",
+ "uOps Per Cycle",
+ "Instructions",
+ "Total Cycles",
+ "Total uOps",
+ ]
+
+ rows, cols = (len(opts.file_names), 7)
+
+ values = [[0 for x in range(cols)] for y in range(rows)]
+
+ for i in range(len(opts.file_names)):
+ values[i][0] = array_of_summary[i].block_rthroughput
+ values[i][1] = array_of_summary[i].dispatch_width
+ values[i][2] = array_of_summary[i].ipc
+ values[i][3] = array_of_summary[i].uops_per_cycle
+ values[i][4] = array_of_summary[i].instructions
+ values[i][5] = array_of_summary[i].total_cycles
+ values[i][6] = array_of_summary[i].total_uops
+
+ fig, axs = plt.subplots(4, 2)
+ fig.suptitle(
+ "Machine code statistics", fontsize=20, fontweight="bold", color="black"
+ )
+ i = 0
+
+ for x in range(4):
+ for y in range(2):
+ cmap = get_cmap("tab20")
+ colors = cmap.colors
+ if not (x == 0 and y == 1) and i < 7:
+ axs[x][y].grid(True, color="grey", linestyle="--")
+ maxValue = 0
+ if i == 0:
+ for j in range(len(opts.file_names)):
+ if maxValue < values[j][i]:
+ maxValue = values[j][i]
+ axs[x][y].bar(
+ 0.3 * j,
+ values[j][i],
+ width=0.1,
+ color=colors[j],
+ label=get_filename_from_path(opts.file_names[j]),
+ )
+ else:
+ for j in range(len(opts.file_names)):
+ if maxValue < values[j][i]:
+ maxValue = values[j][i]
+ axs[x][y].bar(0.3 * j, values[j][i], width=0.1, color=colors[j])
+ axs[x][y].set_axisbelow(True)
+ axs[x][y].set_xlim([-0.3, len(opts.file_names) / 3])
+ axs[x][y].set_ylim([0, maxValue + (maxValue / 2)])
+ axs[x][y].set_title(names[i], fontsize=15, fontweight="bold")
+ axs[x][y].axes.xaxis.set_visible(False)
+ for j in range(len(opts.file_names)):
+ axs[x][y].text(
+ 0.3 * j,
+ values[j][i] + (maxValue / 40),
+ s=str(values[j][i]),
+ color="black",
+ fontweight="bold",
+ fontsize=4,
+ )
+ i = i + 1
+
+ axs[0][1].set_visible(False)
+ fig.legend(prop={"size": 15})
+ figg = plt.gcf()
+ figg.set_size_inches((25, 15), forward=False)
+ if opts.plot_path[0] == "-":
+ plt.savefig("llvm-mca-plot.png", dpi=500)
+ print("The plot was saved within llvm-mca-plot.png")
+ else:
+ plt.savefig(
+ os.path.normpath(os.path.join(opts.plot_path[0], "llvm-mca-plot.png")),
+ dpi=500,
+ )
+ print(
+ "The plot was saved within {}.".format(
+ os.path.normpath(os.path.join(opts.plot_path[0], "llvm-mca-plot.png"))
+ )
+ )
+
+
+# Calculates the average value (summary view) per region.
+def summary_average_code_region(array_of_code_regions, file_name):
+ summary = Summary(file_name, 0, 0, 0, 0, 0, 0, 0, 0, None, None)
+ for i in range(len(array_of_code_regions)):
+ summary.block_rthroughput += array_of_code_regions[i].block_rthroughput
+ summary.dispatch_width += array_of_code_regions[i].dispatch_width
+ summary.ipc += array_of_code_regions[i].ipc
+ summary.instructions += array_of_code_regions[i].instructions
+ summary.iterations += array_of_code_regions[i].iterations
+ summary.total_cycles += array_of_code_regions[i].total_cycles
+ summary.total_uops += array_of_code_regions[i].total_uops
+ summary.uops_per_cycle += array_of_code_regions[i].uops_per_cycle
+ summary.block_rthroughput = round(
+ summary.block_rthroughput / len(array_of_code_regions), 2
+ )
+ summary.dispatch_width = round(
+ summary.dispatch_width / len(array_of_code_regions), 2
+ )
+ summary.ipc = round(summary.ipc / len(array_of_code_regions), 2)
+ summary.instructions = round(summary.instructions / len(array_of_code_regions), 2)
+ summary.iterations = round(summary.iterations / len(array_of_code_regions), 2)
+ summary.total_cycles = round(summary.total_cycles / len(array_of_code_regions), 2)
+ summary.total_uops = round(summary.total_uops / len(array_of_code_regions), 2)
+ summary.uops_per_cycle = round(
+ summary.uops_per_cycle / len(array_of_code_regions), 2
+ )
+ return summary
+
+
+# Based on the obtained results (resource pressure per iter) of llvm-mca tool, draws plots for multiple input files.
+def draw_plot_resource_pressure(
+ array_average_resource_pressure_per_file, opts, name_target_info_resources
+):
+ try:
+ import matplotlib.pyplot as plt
+ except ImportError:
+ print("error: matplotlib.pyplot not found.")
+ sys.exit(1)
+ try:
+ from matplotlib.cm import get_cmap
+ except ImportError:
+ print("error: get_cmap (matplotlib.cm) not found.")
+ sys.exit(1)
+
+ fig, axs = plt.subplots()
+ fig.suptitle(
+ "Resource pressure per iterations",
+ fontsize=20,
+ fontweight="bold",
+ color="black",
+ )
+
+ maxValue = 0
+ for j in range(len(opts.file_names)):
+ if maxValue < max(array_average_resource_pressure_per_file[j]):
+ maxValue = max(array_average_resource_pressure_per_file[j])
+
+ cmap = get_cmap("tab20")
+ colors = cmap.colors
+
+ xticklabels = [None] * len(opts.file_names) * len(name_target_info_resources)
+ index = 0
+
+ for j in range(len(name_target_info_resources)):
+ for i in range(len(opts.file_names)):
+ if i == 0:
+ axs.bar(
+ j * len(opts.file_names) * 10 + i * 10,
+ array_average_resource_pressure_per_file[i][j],
+ width=1,
+ color=colors[j],
+ label=name_target_info_resources[j],
+ )
+ else:
+ axs.bar(
+ j * len(opts.file_names) * 10 + i * 10,
+ array_average_resource_pressure_per_file[i][j],
+ width=1,
+ color=colors[j],
+ )
+ axs.text(
+ j * len(opts.file_names) * 10 + i * 10,
+ array_average_resource_pressure_per_file[i][j] + (maxValue / 40),
+ s=str(array_average_resource_pressure_per_file[i][j]),
+ color=colors[j],
+ fontweight="bold",
+ fontsize=3,
+ )
+ xticklabels[index] = opts.file_names[i]
+ index = index + 1
+
+ axs.set_xticks(
+ [
+ j * len(opts.file_names) * 10 + i * 10
+ for j in range(len(name_target_info_resources))
+ for i in range(len(opts.file_names))
+ ]
+ )
+ axs.set_xticklabels(xticklabels, rotation=65)
+
+ axs.set_axisbelow(True)
+ axs.set_xlim([-0.5, len(opts.file_names) * len(name_target_info_resources) * 10])
+ axs.set_ylim([0, maxValue + maxValue / 10])
+
+ fig.legend(prop={"size": 15})
+ figg = plt.gcf()
+ figg.set_size_inches((25, 15), forward=False)
+ if opts.plot_path[0] == "-":
+ plt.savefig("llvm-mca-plot-resource-pressure.png", dpi=500)
+ print("The plot was saved within llvm-mca-plot-resource-pressure.png")
+ else:
+ plt.savefig(
+ os.path.normpath(
+ os.path.join(opts.plot_path[0], "llvm-mca-plot-resource-pressure.png")
+ ),
+ dpi=500,
+ )
+ print(
+ "The plot was saved within {}.".format(
+ os.path.normpath(
+ os.path.join(
+ opts.plot_path[0], "llvm-mca-plot-resource-pressure.png"
+ )
+ )
+ )
+ )
+
+
+# Calculates the average value (resource pressure per iter) per region.
+def average_code_region_resource_pressure(array_of_code_regions, file_name):
+ resource_pressure_per_iter_one_file = [0] * len(
+ array_of_code_regions[0].iteration_resource_pressure
+ )
+ for i in range(len(array_of_code_regions)):
+ for j in range(len(array_of_code_regions[i].iteration_resource_pressure)):
+ if array_of_code_regions[i].iteration_resource_pressure[j] != "-":
+ resource_pressure_per_iter_one_file[j] += float(
+ array_of_code_regions[i].iteration_resource_pressure[j]
+ )
+ for i in range(len(resource_pressure_per_iter_one_file)):
+ resource_pressure_per_iter_one_file[i] = round(
+ resource_pressure_per_iter_one_file[i] / len(array_of_code_regions), 2
+ )
+ return resource_pressure_per_iter_one_file
+
+
def Main():
parser = argparse.ArgumentParser()
opts = parse_program_args(parser)
+ if not verify_program_inputs(opts):
+ parser.print_help()
+ sys.exit(1)
+
matrix_of_code_regions = [None] * len(opts.file_names)
for i in range(len(opts.file_names)):
matrix_of_code_regions[i] = run_llvm_mca_tool(opts, opts.file_names[i])
- console_print_results(matrix_of_code_regions, opts)
+ if not opts.plot and not opts.plot_resource_pressure:
+ console_print_results(matrix_of_code_regions, opts)
+ else:
+ if opts.plot:
+ array_average_summary_per_file = [None] * len(matrix_of_code_regions)
+ for j in range(len(matrix_of_code_regions)):
+ array_average_summary_per_file[j] = summary_average_code_region(
+ matrix_of_code_regions[j], opts.file_names[j]
+ )
+ draw_plot_files_summary(array_average_summary_per_file, opts)
+ if opts.plot_resource_pressure:
+ array_average_resource_pressure_per_file = [None] * len(
+ matrix_of_code_regions
+ )
+ for j in range(len(matrix_of_code_regions)):
+ array_average_resource_pressure_per_file[
+ j
+ ] = average_code_region_resource_pressure(
+ matrix_of_code_regions[j], opts.file_names[j]
+ )
+ draw_plot_resource_pressure(
+ array_average_resource_pressure_per_file,
+ opts,
+ matrix_of_code_regions[0][0].name_target_info_resources,
+ )
if __name__ == "__main__":
More information about the llvm-commits
mailing list