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

286 lines
12 KiB
Python

# ##########################################################################
# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
# ##########################################################################
import argparse
import collections
import csv
import math
import os
import re
import shlex
import sys
from itertools import chain, repeat
from subprocess import Popen, PIPE
#################################################
######### Benchmark suites definitions ##########
#################################################
common = '--iters 3 --perf 1' #always do 3 iterations in perf mode
"""
SYEVD tests are run, for the given precision and sizes, with vectors and without vectors
"""
def syevd_heevd_suite(*, suite, precision, sizenormal, sizebatch):
fn = 'syevd' if precision == 's' or precision == 'd' else 'heevd'
size = sizenormal
for v in ['V', 'N']:
if v == 'V': vv = 'yes'
else: vv = 'no'
for s in size:
row = {'name': precision+suite, 'name_test': suite, 'function': fn, 'precision': precision, 'evect': vv, 'n': s}
yield (row, s, f'-f {fn} -r {precision} --evect {v} -n {s} {common}')
"""
SYEVDX tests are run, for the given precision and sizes, with vectors and without vectors and
computing 20, 60 and 100 percent of the eigenvalues
"""
def syevdx_heevdx_suite(*, suite, precision, sizenormal, sizebatch):
fn = 'syevdx' if precision == 's' or precision == 'd' else 'heevdx'
size=sizenormal
for per in [20, 60, 100]:
for v in ['V', 'N']:
if v == 'V': vv = 'yes'
else: vv = 'no'
for s in size:
p = int(s * per / 100)
if p == 0: p = 1
row = {'name': precision+suite, 'name_test': suite, 'function': fn, 'precision': precision, 'range': per, 'evect': vv, 'n': s}
yield (row, s, f'-f {fn} -r {precision} --erange I --il 1 --iu {p} --evect {v} -n {s} {common}')
"""
SYEVJ tests are run, for the given precision and sizes, with vectors and without vectors
"""
def syevj_heevj_suite(*, suite, precision, sizenormal, sizebatch):
fn = 'syevj' if precision == 's' or precision == 'd' else 'heevj'
size = sizenormal
for v in ['V', 'N']:
if v == 'V': vv = 'yes'
else: vv = 'no'
for s in size:
row = {'name': precision+suite, 'name_test': suite, 'function': fn, 'precision': precision, 'evect': vv, 'n': s}
yield (row, s, f'-f {fn} -r {precision} --evect {v} -n {s} {common}')
"""
SYEVJBATCH tests are run, for the given precision and sizes, with vectors and without vectors
"""
def syevj_heevjBatch_suite(*, suite, precision, sizenormal, sizebatch):
fn = 'syevj_strided_batched' if precision == 's' or precision == 'd' else 'heevj_strided_batched'
size = sizebatch
for v in ['V', 'N']:
if v == 'V': vv = 'yes'
else: vv = 'no'
for s, bc in size:
row = {'name': precision+suite, 'name_test': suite, 'function': fn, 'precision': precision, 'evect': vv, 'batch_count': bc, 'n': s}
yield (row, s, f'-f {fn} -r {precision} --evect {v} --batch_count {bc} -n {s} {common}')
"""
GESVD tests are run, for the given precision and sizes, with vectors and without vectors
"""
def gesvd_suite(*, suite, precision, sizenormal, sizebatch):
fn = 'gesvd'
size = sizenormal
for v in ['V', 'N']:
if v == 'V': vv = 'yes'
else: vv = 'no'
for s in size:
row = {'name': precision+suite, 'name_test': suite, 'function': fn, 'precision': precision, 'svect': vv, 'n': s}
yield (row, s, f'-f {fn} -r {precision} --left_svect {v} --right_svect {v} -m {s} {common}')
"""
GESVDJ tests are run, for the given precision and sizes, with vectors and without vectors
"""
def gesvdj_suite(*, suite, precision, sizenormal, sizebatch):
fn = 'gesvdj'
size = sizenormal
for v in ['V', 'N']:
if v == 'V': vv = 'yes'
else: vv = 'no'
for s in size:
row = {'name': precision+suite, 'name_test': suite, 'function': fn, 'precision': precision, 'svect': vv, 'n': s}
yield (row, s, f'-f {fn} -r {precision} --left_svect {v} --right_svect {v} -m {s} {common}')
"""
GESVDJBATCH tests are run, for the given precision and sizes, with vectors and without vectors
"""
def gesvdjBatch_suite(*, suite, precision, sizenormal, sizebatch):
fn = 'gesvdj_strided_batched'
size = sizebatch
for v in ['V', 'N']:
if v == 'V': vv = 'yes'
else: vv = 'no'
for s, bc in size:
row = {'name': precision+suite, 'name_test': suite, 'function': fn, 'precision': precision, 'evect': vv, 'batch_count': bc, 'n': s}
yield (row, s, f'-f {fn} -r {precision} --left_svect {v} --right_svect {v} --batch_count {bc} -m {s} {common}')
"""
POTRF tests are run with the given precision and sizes
"""
def potrf_suite(*, suite, precision, sizenormal, sizebatch):
fn = 'potrf'
size = sizenormal
for s in size:
row = {'name': precision+suite, 'name_test': suite, 'function': fn, 'precision': precision, 'n': s}
yield (row, s, f'-f {fn} -r {precision} -n {s} {common}')
"""
POTRFBATCH tests are run with the given precision and sizes
"""
def potrfBatch_suite(*, suite, precision, sizenormal, sizebatch):
fn = 'potrf_batched'
size = sizebatch
for s, bc in size:
row = {'name': precision+suite, 'name_test': suite, 'function': fn, 'precision': precision, 'batch_count': bc, 'n': s}
yield (row, s, f'-f {fn} -r {precision} --batch_count {bc} -n {s} {common}')
"""
GEQRF tests are run, for the given precision and number of rows,
with 160, 576, 1088, 2176, and 4352 columns and also for the square case (#rows = #columns)
"""
def geqrf_suite(*, suite, precision, sizenormal, sizebatch):
fn = 'geqrf'
size=sizenormal
for nc in [0, 160, 576, 1088, 2176, 4352]:
if nc == 0: nn = 'sq'
else: nn = nc
for s in size:
if nc == 0: n = s
else: n = nc
row = {'name': precision+suite, 'name_test': suite, 'function': fn, 'precision': precision, 'cols': nn, 'n': s}
yield (row, s, f'-f {fn} -r {precision} -n {n} -m {s} {common}')
suites = {
'syevd': syevd_heevd_suite,
'syevdx': syevdx_heevdx_suite,
'syevj': syevj_heevj_suite,
'syevjBatch': syevj_heevjBatch_suite,
'gesvd': gesvd_suite,
'gesvdj': gesvdj_suite,
'gesvdjBatch': gesvdjBatch_suite,
'potrf': potrf_suite,
'potrfBatch': potrfBatch_suite,
'geqrf': geqrf_suite}
#################################################
############## Helper functions #################
#################################################
"""
SETUP_VPRINT defines the function vprint as the normal print function when
verbose output is enabled, or alternatively as a function that does nothing.
"""
def setup_vprint(args):
global vprint
vprint = print if args.verbose else lambda *a, **k: None
"""
CALL_ROCSOLVER_BENCH executes system call to the benchmark
client executable with the given list of arguments
"""
def call_rocsolver_bench(bench_executable, *args):
cmd = [bench_executable]
for arg in args:
if isinstance(arg, str):
cmd.extend(shlex.split(arg, False, False))
elif isinstance(arg, collections.Sequence):
cmd.extend(arg)
else:
cmd.push(str(arg))
process = Popen(cmd, stdout=PIPE, stderr=PIPE)
vprint('executing {}'.format(' '.join(cmd)))
stdout, stderr = process.communicate()
return (str(stdout, encoding='utf-8', errors='surrogateescape'),
str(stderr, encoding='utf-8', errors='surrogateescape'),
process.returncode)
"""
EXECUTE_BENCHMARKS collects the arguments for the benchmark client, calls
the client, gets the resulting time, and put everything in file or screen
"""
def execute_benchmarks(output_file, suite, precision, case, bench_executable):
init = False
benchmark_generator = suites[suite];
sizenormal = list(chain(range(2, 64, 8), range(64, 256, 32), range(256, 1024, 64)))
sizebatch = list(chain(zip(range(2, 64, 4), repeat(5000)), zip(range(72, 164, 8), repeat(2500))))
if case == 'medium' or case == 'large':
sizenormal += list(chain(range(1024, 2048, 64), range(2048, 4096, 128)))
sizebatch += list(chain(zip(range(168, 260, 8), repeat(2500)), zip(range(272, 520, 16), repeat(1000))))
if case == 'large':
sizenormal += list(chain(range(4096, 8192, 256), range(8192, 12300, 512)))
sizebatch += list(chain(zip(range(544, 1050, 32), repeat(500)), zip(range(1088, 2050, 64), repeat(50))))
for row, n, bench_args in benchmark_generator(suite=suite, precision=precision, sizenormal=sizenormal, sizebatch=sizebatch):
out, err, exitcode = call_rocsolver_bench(bench_executable, bench_args)
if exitcode != 0:
sys.exit("rocsolver-bench call failure: {}".format(err))
time = float(out)
row['gpu_time_us'] = time
row['log_n'] = math.log10(n)
row['log_gpu_time_us'] = math.log10(time)
if not init:
results = csv.DictWriter(output_file, fieldnames=row.keys(), extrasaction='raise', dialect='excel')
results.writeheader()
init = True
results.writerow(row)
#################################################
######### Main functions ########################
#################################################
if __name__ == '__main__':
parser = argparse.ArgumentParser(prog='rocsolver-perfoptim-suite',
description='Executes a selected suite of benchmarks and collates the results.')
parser.add_argument('-v','--verbose',
action='store_true',
help='display more information about operations being performed')
parser.add_argument('--exe',
default='../../build/release/clients/staging/rocsolver-bench',
help='the benchmark executable to run')
parser.add_argument('-o',
dest='output_path',
default=None,
help='the output file name for the benchmark results')
parser.add_argument('suite',
choices=suites.keys(),
help='the set of benchmarks to run')
parser.add_argument('precision',
choices=['s', 'd', 'c' , 'z'],
help='the precision to use for the benchmarks')
parser.add_argument('case',
choices=['small', 'medium', 'large'],
help='the size case to use for the benchmarks')
args = parser.parse_args()
setup_vprint(args)
if args.output_path is not None:
with open(args.output_path, 'w', buffering=1, encoding='utf-8') as output_file:
execute_benchmarks(output_file, args.suite, args.precision, args.case, args.exe)
else:
execute_benchmarks(sys.stdout, args.suite, args.precision, args.case, args.exe)