mirror of
https://github.com/amd/blis.git
synced 2026-04-13 04:20:29 +00:00
Standardize format of AMD copyright notice. AMD-Internal: [CPUPL-3519] Change-Id: I98530e58138765e5cd5bc0c97500506801eb0bf0
310 lines
10 KiB
Python
Executable File
310 lines
10 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
#
|
|
# BLIS
|
|
# An object-based framework for developing high-performance BLAS-like
|
|
# libraries.
|
|
#
|
|
# Copyright (C) 2018, The University of Texas at Austin
|
|
# Copyright (C) 2018 - 2023, 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:
|
|
# - Redistributions of source code must retain the above copyright
|
|
# notice, this list of conditions and the following disclaimer.
|
|
# - 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.
|
|
# - Neither the name(s) of the copyright holder(s) nor the names of its
|
|
# contributors may be used to endorse or promote products derived
|
|
# from this software without specific prior written permission.
|
|
#
|
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
|
|
# HOLDER 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 modules
|
|
import os
|
|
import sys
|
|
import getopt
|
|
import re
|
|
import subprocess
|
|
import time
|
|
import statistics
|
|
|
|
|
|
def print_usage():
|
|
|
|
my_print( " " )
|
|
my_print( " %s" % script_name )
|
|
my_print( " " )
|
|
my_print( " Field G. Van Zee" )
|
|
my_print( " " )
|
|
my_print( " Repeatedly run a test driver and accumulate statistics for the" )
|
|
my_print( " output." )
|
|
my_print( " " )
|
|
my_print( " Usage:" )
|
|
my_print( " " )
|
|
my_print( " %s [options] drivername" % script_name )
|
|
my_print( " " )
|
|
my_print( " Arguments:" )
|
|
my_print( " " )
|
|
my_print( " drivername The filename/path of the test driver to run. The" )
|
|
my_print( " test driver must output its performance data to" )
|
|
my_print( " standard output." )
|
|
my_print( " " )
|
|
my_print( " The following options are accepted:" )
|
|
my_print( " " )
|
|
my_print( " -c num performance column index" )
|
|
my_print( " Find the performance result in column index <num> of" )
|
|
my_print( " the test driver's output. Here, a column is defined" )
|
|
my_print( " as a contiguous sequence of non-whitespace characters," )
|
|
my_print( " with the column indices beginning at 0. By default," )
|
|
my_print( " the second-to-last column index in the output is used." )
|
|
my_print( " " )
|
|
my_print( " -d delay sleep() delay" )
|
|
my_print( " Wait <delay> seconds after each execution of the" )
|
|
my_print( " test driver. The default delay is 0." )
|
|
my_print( " " )
|
|
my_print( " -n niter number of iterations" )
|
|
my_print( " Execute the test driver <niter> times. The default" )
|
|
my_print( " value is 10." )
|
|
my_print( " " )
|
|
my_print( " -q quiet; summary only" )
|
|
my_print( " Do not output statistics after every new execution of" )
|
|
my_print( " the test driver; instead, only output the final values" )
|
|
my_print( " after all iterations are complete. The default is to" )
|
|
my_print( " output updated statistics after each iteration." )
|
|
my_print( " " )
|
|
my_print( " -h help" )
|
|
my_print( " Output this information and exit." )
|
|
my_print( " " )
|
|
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
def my_print( s ):
|
|
|
|
sys.stdout.write( "%s\n" % s )
|
|
#sys.stdout.flush()
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
# Global variables.
|
|
script_name = None
|
|
output_name = None
|
|
|
|
def main():
|
|
|
|
global script_name
|
|
global output_name
|
|
|
|
# Obtain the script name.
|
|
path, script_name = os.path.split(sys.argv[0])
|
|
|
|
output_name = script_name
|
|
|
|
# Default values for optional arguments.
|
|
#perf_col = 9
|
|
perf_col = -1
|
|
delay = 0
|
|
niter = 10
|
|
quiet = False
|
|
|
|
# Process our command line options.
|
|
try:
|
|
opts, args = getopt.getopt( sys.argv[1:], "c:d:n:hq" )
|
|
|
|
except getopt.GetoptError as err:
|
|
# print help information and exit:
|
|
my_print( str(err) ) # will print something like "option -a not recognized"
|
|
print_usage()
|
|
sys.exit(2)
|
|
|
|
for opt, optarg in opts:
|
|
if opt == "-c":
|
|
perf_col = optarg
|
|
elif opt == "-d":
|
|
delay = optarg
|
|
elif opt == "-n":
|
|
niter = optarg
|
|
elif opt == "-q":
|
|
quiet = True
|
|
elif opt == "-h":
|
|
print_usage()
|
|
sys.exit()
|
|
else:
|
|
print_usage()
|
|
sys.exit()
|
|
|
|
# Print usage if we don't have exactly one argument.
|
|
if len( args ) != 1:
|
|
print_usage()
|
|
sys.exit()
|
|
|
|
# Acquire our only mandatory argument: the name of the test driver.
|
|
driverfile = args[0]
|
|
|
|
#my_print( "test driver: %s" % driverfile )
|
|
#my_print( "column num: %s" % perf_col )
|
|
#my_print( "delay: %s" % delay )
|
|
#my_print( "num iter: %s" % niter )
|
|
|
|
# Build a list of iterations.
|
|
iters = range( int(niter) )
|
|
|
|
# Run the test driver once to detect the number of lines of output.
|
|
p = subprocess.run( driverfile, stdout=subprocess.PIPE )
|
|
lines0 = p.stdout.decode().splitlines()
|
|
num_lines0 = int(len(lines0))
|
|
|
|
# Initialize the list of lists (one list per performance result).
|
|
aperf = []
|
|
for i in range( num_lines0 ):
|
|
aperf.append( [] )
|
|
|
|
for it in iters:
|
|
|
|
# Run the test driver.
|
|
p = subprocess.run( driverfile, stdout=subprocess.PIPE )
|
|
|
|
# Acquire the lines of output.
|
|
lines = p.stdout.decode().splitlines()
|
|
|
|
# Accumulate the test driver's latest results into aperf.
|
|
for i in range( num_lines0 ):
|
|
|
|
# Parse the current line to find the performance value.
|
|
line = lines[i]
|
|
words = line.split()
|
|
if perf_col == -1:
|
|
perf = words[ len(words)-2 ]
|
|
else:
|
|
perf = words[ int(perf_col) ]
|
|
|
|
# As unlikely as it is, guard against Inf and NaN.
|
|
if float(perf) == float('Inf') or \
|
|
float(perf) == -float('Inf') or \
|
|
float(perf) == float('NaN'): perf = 0.0
|
|
|
|
# Add the performance value to the list at the ith entry of aperf.
|
|
aperf[i].append( float(perf) )
|
|
|
|
# Compute stats for the current line.
|
|
avgp = statistics.mean( aperf[i] )
|
|
maxp = max( aperf[i] )
|
|
minp = min( aperf[i] )
|
|
|
|
# Only compute stdev() when we have two or more data points.
|
|
if len( aperf[i] ) > 1: stdp = statistics.stdev( aperf[i] )
|
|
else: stdp = 0.0
|
|
|
|
# Construct a string to match the performance value and then
|
|
# use that string to search-and-replace with four format specs
|
|
# for the min, avg, max, and stdev values computed above.
|
|
search = '%8s' % perf
|
|
newline = re.sub( str(search), ' %7.2f %7.2f %7.2f %6.2f', line )
|
|
|
|
# Search for the column index range that would be present if this were
|
|
# matlab-compatible output. The index range will typically be 1:n,
|
|
# where n is the number of columns of data.
|
|
found_index = False
|
|
for word in words:
|
|
if re.match( '1:', word ):
|
|
index_str = word
|
|
found_index = True
|
|
break
|
|
|
|
# If we find the column index range, we need to update it to reflect
|
|
# the replacement of one column of data with four, for a net increase
|
|
# of columns. We do so via another instance of re.sub() in which we
|
|
# search for the old index string and replace it with the new one.
|
|
if found_index:
|
|
last_col = int(index_str[2]) + 3
|
|
new_index_str = '1:%1s' % last_col
|
|
newline = re.sub( index_str, new_index_str, newline )
|
|
|
|
# If the quiet flag was not give, output the intermediate results.
|
|
if not quiet:
|
|
print( newline % ( float(minp), float(avgp), float(maxp), float(stdp) ) )
|
|
|
|
# Flush stdout after each set of output prior to sleeping.
|
|
sys.stdout.flush()
|
|
|
|
# Sleep for a bit until the next iteration.
|
|
time.sleep( int(delay) )
|
|
|
|
# If the quiet flag was given, output the final results.
|
|
if quiet:
|
|
|
|
for i in range( num_lines0 ):
|
|
|
|
# Parse the current line to find the performance value (only
|
|
# needed for call to re.sub() below).
|
|
line = lines0[i]
|
|
words = line.split()
|
|
if perf_col == -1:
|
|
perf = words[ len(words)-2 ]
|
|
else:
|
|
perf = words[ int(perf_col) ]
|
|
|
|
# Compute stats for the current line.
|
|
avgp = statistics.mean( aperf[i] )
|
|
maxp = max( aperf[i] )
|
|
minp = min( aperf[i] )
|
|
|
|
# Only compute stdev() when we have two or more data points.
|
|
if len( aperf[i] ) > 1: stdp = statistics.stdev( aperf[i] )
|
|
else: stdp = 0.0
|
|
|
|
# Construct a string to match the performance value and then
|
|
# use that string to search-and-replace with four format specs
|
|
# for the min, avg, max, and stdev values computed above.
|
|
search = '%8s' % perf
|
|
newline = re.sub( str(search), ' %7.2f %7.2f %7.2f %6.2f', line )
|
|
|
|
# Search for the column index range that would be present if this were
|
|
# matlab-compatible output. The index range will typically be 1:n,
|
|
# where n is the number of columns of data.
|
|
found_index = False
|
|
for word in words:
|
|
if re.match( '1:', word ):
|
|
index_str = word
|
|
found_index = True
|
|
break
|
|
|
|
# If we find the column index range, we need to update it to reflect
|
|
# the replacement of one column of data with four, for a net increase
|
|
# of columns. We do so via another instance of re.sub() in which we
|
|
# search for the old index string and replace it with the new one.
|
|
if found_index:
|
|
last_col = int(index_str[2]) + 3
|
|
new_index_str = '1:%1s' % last_col
|
|
newline = re.sub( index_str, new_index_str, newline )
|
|
|
|
# Output the results for the current line.
|
|
print( newline % ( float(minp), float(avgp), float(maxp), float(stdp) ) )
|
|
|
|
# Flush stdout afterwards.
|
|
sys.stdout.flush()
|
|
|
|
|
|
# Return from main().
|
|
return 0
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|