Files
TheRock/rocm-libraries/projects/rocblas/scripts/performance/blas/combine_plots.py
T
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

208 lines
10 KiB
Python

#!/usr/bin/env python3
"""Copyright (C) 2022-2023 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell cop-
ies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IM-
PLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNE-
CTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"""
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 rocblas-bench and rocBLAS\' performancereport.py. Can also be used with hipblas-bench and hipBLAS\' 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='rocblas-bench')
parser.add_argument('--search_str', type=str, help='A search string to find data line in data files.', dest='search_string', default='rocblas-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='rocblas-Gflops', gflops_str='rocblas-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 = 'rocblas-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 = 'rocblas-bench', search_string = 'rocblas-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)