Files
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

187 lines
8.8 KiB
Python

#!/usr/bin/env python3
import argparse
import os
import re
import sys
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import numpy as np
parser = argparse.ArgumentParser(description='Used with completed datasets from performancereport.py to compare different functions\' performance.\n' +
'Works with hipblas-bench and hipBLAS\' performancereport.py. Can also be used with rocblas-bench and rocBLAS\' performancereport.py with ' +
'command line arguments.',
epilog='Example usage: ./combine_plots.py -s N -d ./output_gemm/run00 -d ./output_symm/run00')
parser.add_argument('-s', '--size_arg', help='Value which to base the x axis "size" on.', dest='size_arg', default='N')
parser.add_argument('-d', '--dir', action='append', help='Each directory containing data which you would like to compare.', dest='dirs', required=True)
parser.add_argument('-t', '--titles', action='append', help='The subtitle name for the resulting plot for each directory, in the same order as the arguments passed in --dir.', dest='titles')
parser.add_argument('-f', '--savedir', type=str, help='Directory where resulting plots will be saved.', dest='savedir', default='combine_plots')
parser.add_argument('-x', '--executable', type=str, help='Name of the executable used to run perf tests.', dest='executable_name', default='hipblas-bench')
parser.add_argument('--search_str', type=str, help='A search string to find data line in data files.', dest='search_string', default='hipblas-Gflops')
args = parser.parse_args()
def get_all_files(directory_str):
"""
returns a list of *.out files in the given directory.
Parameters:
directory_str (string): the directory which we are gathering files from
Returns:
ret_list (list[string]): a list of file paths in the directory which end in .out
"""
ret_list = []
# only reading .out files as they contain the input parameters we need (func name, precision),
# along with the output parameters we need (gflops)
for f in os.listdir(os.fsencode(directory_str)):
filename = os.fsdecode(f)
if filename.endswith(".out"):
ret_list.append(os.path.join(directory_str, filename))
return ret_list
def get_output_val_from_file(filename, output_param='hipblas-Gflops', gflops_str='hipblas-Gflops'):
"""
parses through file and returns the val as given in the file.
Parameters:
filename (string): path of the file to parse.
output_param (string): the output parameter which we are parsing the file for.
gflops_str (string): string to parse file for in csv portion.
Returns:
value (string): the gflops as listed in the file, refer to example file (TODO).
"""
if os.path.exists(filename):
lines = open(filename, 'r').readlines()
for i in range(0, len(lines)):
if(output_param in lines[i]):
arg_line = lines[i].split(",")
data_line = re.split(r',\s*(?![^()]*\))', lines[i+1])
idx = arg_line.index(gflops_str)
return data_line[idx]
return '-1'
def get_input_param_from_file(filename, input_param, executable_name = 'hipblas-bench'):
"""
parses through file and returns the function name as given in the file (by the -f argument passed to xxx-bench).
Parameters:
filename (string): path of the file to parse.
input_param (string): the input parameter which we are parsing the file for. For example, '-f' to parse function name.
executable_name (string): executable name that we can use to parse the function name in the data file
Returns:
funcname (string): function name as given by the -f argument passed to xxx-bench.
"""
if os.path.exists(filename):
lines = open(filename, 'r').readlines()
for line in lines:
if executable_name in line:
linesplit = line.split()
return linesplit[linesplit.index(input_param)+1]
raise RuntimeError('Cannot find input param ' + input_param + ' in file: ' + filename)
def get_data_from_directories(directories, size_param = 'N', executable_name = 'hipblas-bench', search_string = 'hipblas-Gflops'):
"""
For each directory in directories, gathers function name, precisions, sizes, and gflops from within files in that directory and returns it.
Parameters:
directories (list[string]): list of directory names to gather information from
size_param (string): parameter in file which defines the "size"
executable_name (string): executable name that we can use to parse the function name in the data file
search_string (string): the string which we used to find the data line in the .out file
Returns:
res_dicts (list[dict{string: list[(int, float)]}]): for each directory; for each precision in any file within that directory, this dictionary contains a list
of tuples for that precision containing sizes (as defined by size_param) and the corresponding
gflops value from a file.
res_funcs (list[string]): a list of function names, one function name is gathered from each directory. Each function name corresponds to dictionary
at the same index in res_dicts.
"""
res_dicts = []
res_funcs = []
for directory in directories:
cur_funcname = None
cur_dict = {}
for f in get_all_files(directory):
# append funcname to list of funcnames, only for first file in each directory as we assume
# each directory has data for only one function (but multiple precisions)
if cur_funcname is None:
cur_funcname = get_input_param_from_file(f, '-f')
prec = get_input_param_from_file(f, '-r', executable_name)
# a tuple of (size, gflops) as gathered from the current file
size_perf_tuple = (int(get_output_val_from_file(f, search_string, size_param)), float(get_output_val_from_file(f, search_string)))
if prec in cur_dict:
cur_dict[prec].append(size_perf_tuple)
else:
cur_dict[prec] = [size_perf_tuple]
res_dicts.append(cur_dict)
res_funcs.append(cur_funcname)
return res_dicts, res_funcs
def plot_data(gflops_dicts, titles, savedir, size_arg = 'N'):
"""
plots gflops data from dictionaries, one plot for each common precision present in all dictionaries.
Parameters:
gflops_dicts (list[dict{string: list[(int, float)]}]): data as given by :func:`get_data_from_directories`.
titles (list[string]): a list of titles for each data set to be plotted and used as a savefile name.
savedir (string): directory where resulting plots will be saved.
size_arg (string): x axis title on plot.
"""
if len(gflops_dicts) == 0:
return
gflops_dict0 = gflops_dicts[0]
for prec, _ in gflops_dict0.items():
colors=iter(cm.rainbow(np.linspace(0,1,len(gflops_dicts))))
figure, axes = plt.subplots(figsize=(7,7))
for gflops_dict, funcname in zip(gflops_dicts, titles):
cur_color = next(colors)
if prec not in gflops_dict:
continue
gflops = gflops_dict[prec]
gflops.append((0, 0)) # I prefer having a 0 at the bottom so the performance looks more accurate
sorted_tuples = sorted(gflops)
sorted_sizes = [x[0] for x in sorted_tuples]
sorted_gflops = [x[1] for x in sorted_tuples]
axes.scatter(sorted_sizes, sorted_gflops, color=cur_color, label=funcname)
axes.plot(sorted_sizes, sorted_gflops, '-ok', color=cur_color)
axes.set_xlabel('='.join(size_arg)) # in case we add multiple params
axes.set_ylabel('gflops')
# magic numbers from performancereport.py to make plots look nice
axes.legend(fontsize=10, bbox_to_anchor=(0., 1.02, 1., .102), loc='lower left',
mode='expand', borderaxespad=0.)
figure.tight_layout(rect=(0,0.05,1.0,1.0))
filename = ''
for func in titles:
if filename != '':
filename += '_'
filename += func
filename += '_' + prec
if not os.path.exists(savedir):
os.makedirs(savedir)
figure.savefig(os.path.join(os.getcwd(), savedir, filename))
gflops, funcnames = get_data_from_directories(args.dirs, args.size_arg, args.executable_name, args.search_string)
if args.titles:
if len(args.titles) == len(gflops):
funcnames = args.titles
else:
raise RuntimeError('Must have same amount of -t parameters as -d parameters, or have no -t parameters.')
plot_data(gflops, funcnames, args.savedir, args.size_arg)