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
347 lines
15 KiB
Python
347 lines
15 KiB
Python
################################################################################
|
|
#
|
|
# Copyright (C) 2016-2024 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
|
|
# copies 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
|
|
# IMPLIED, 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 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
# SOFTWARE.
|
|
#
|
|
################################################################################
|
|
|
|
# Generates four rocblas-bench input files from the library logic files: beta 0/1 + rotating buffer 0/1. The cold and hot iteration counts are based on the performance in the library logic.
|
|
|
|
# Usage:
|
|
# $ python3 rocblas-benchInputCreator.py [-v] [-i <init>] <lib logic dir> <output dir>
|
|
|
|
# creates the benchmark yamls and verification files with default iterations and initialization:
|
|
# $ python3 rocblas-benchInputCreator.py -v ../libLogics ./
|
|
|
|
# creates the benchmark yamls for 3s of benchamrking with default initialization:
|
|
# $ python3 rocblas-benchInputCreator.py -v -d 3.0 ../libLogics ./
|
|
|
|
# creates the benchmark yamls and verification files with hpl initialization:
|
|
# $ python3 rocblas-benchInputCreator.py -v -i hpl ../libLogics ./
|
|
|
|
# creates the benchmark yamls using the default initialization (trig or int)
|
|
# $ python3 rocblas-benchInputCreator.py ../libLogics ./
|
|
|
|
import argparse
|
|
import os
|
|
import yaml
|
|
import math
|
|
|
|
from yaml import SafeDumper as yamlDumper
|
|
from yaml import SafeLoader as yamlLoader
|
|
|
|
typeIndexToName = {0: "f32_r", 1: "f64_r", 2: "f32_c", 3: "f64_c", 4: "f16_r", 5: "i8_r", 6: "i32_r", 7: "bf16_r", 8: "i8_r", 10: "f8_r", 11: "bf8_r", 12: "f8b8", 13: "b8f8"}
|
|
|
|
def parseArgs():
|
|
argParser = argparse.ArgumentParser()
|
|
|
|
h = {"libLogic" : "Input library logic file",
|
|
"outDir" : "Output directory for rocBLAS-bench yaml files",
|
|
"verify" : "Also output verify version of yaml files",
|
|
"initial" : "Matrix initialization: hpl, trig, int. The default is trig for non Int8 datatype, and int for Int8.",
|
|
"duration" : "total benchmark duration in seconds. Default is 0 (10/2 iterations)"
|
|
}
|
|
|
|
argParser.add_argument("libLogic", metavar="logic-file", type=str, help=h["libLogic"])
|
|
argParser.add_argument("outDir", metavar="output-dir", type=str, help=h["outDir"])
|
|
argParser.add_argument("--verify", "-v", action="store_true", help=h["verify"])
|
|
argParser.add_argument("--initialization", "-i", action="store", type=str, default = 'trig', help=h["initial"])
|
|
argParser.add_argument("--duration", "-d", action="store", type=float, default = 0.0, help=h["duration"])
|
|
|
|
return argParser.parse_args()
|
|
|
|
def getProblemType(problem):
|
|
# transA/B, a/b/c/d/compute_type
|
|
problemDict = {}
|
|
|
|
if problem["ComplexConjugateA"]:
|
|
problemDict["transA"] = "C"
|
|
elif problem["TransposeA"]:
|
|
problemDict["transA"] = "T"
|
|
else:
|
|
problemDict["transA"] = "N"
|
|
|
|
if problem["ComplexConjugateB"]:
|
|
problemDict["transB"] = "C"
|
|
elif problem["TransposeB"]:
|
|
problemDict["transB"] = "T"
|
|
else:
|
|
problemDict["transB"] = "N"
|
|
|
|
problemDict["a_type"] = typeIndexToName[problem["DataType"]]
|
|
problemDict["b_type"] = typeIndexToName[problem["DataType"]]
|
|
problemDict["c_type"] = typeIndexToName[problem["DestDataType"]]
|
|
problemDict["d_type"] = typeIndexToName[problem["DestDataType"]]
|
|
|
|
f8gemm = True if (problem["DataType"]>=10) else False # is it f8
|
|
|
|
if "ComputeDataType" in problem:
|
|
compType = typeIndexToName[problem["ComputeDataType"]]
|
|
if f8gemm: # f8 gemm
|
|
if (typeIndexToName[problem["DataType"]] =="f8b8" and typeIndexToName[problem["DestDataType"]]=="f16_r"): # for F8B8HS
|
|
problemDict["a_type"] = "f16_r"
|
|
problemDict["b_type"] = "f16_r"
|
|
problemDict["composite_compute_type"] = "f8_bf8_f32"
|
|
elif (typeIndexToName[problem["DataType"]] =="b8f8" and typeIndexToName[problem["DestDataType"]]=="f16_r"): # for B8F8HS
|
|
problemDict["a_type"] = "f16_r"
|
|
problemDict["b_type"] = "f16_r"
|
|
problemDict["composite_compute_type"] = "bf8_f8_f32"
|
|
elif (typeIndexToName[problem["DataType"]] =="f8_r" and typeIndexToName[problem["DestDataType"]]=="f16_r"): # for F8HS
|
|
problemDict["a_type"] = "f16_r"
|
|
problemDict["b_type"] = "f16_r"
|
|
problemDict["composite_compute_type"] = "f8_f8_f32"
|
|
elif (typeIndexToName[problem["DataType"]] =="bf8_r" and typeIndexToName[problem["DestDataType"]]=="f16_r"): # for B8HS
|
|
problemDict["a_type"] = "f16_r"
|
|
problemDict["b_type"] = "f16_r"
|
|
problemDict["composite_compute_type"] = "bf8_bf8_f32"
|
|
elif (typeIndexToName[problem["DataType"]] =="f8b8" and typeIndexToName[problem["DestDataType"]]=="f32_r"): # for B8SS
|
|
problemDict["a_type"] = "f8_r"
|
|
problemDict["b_type"] = "bf8_r"
|
|
problemDict["composite_compute_type"] = "f32"
|
|
elif (typeIndexToName[problem["DataType"]] =="b8f8" and typeIndexToName[problem["DestDataType"]]=="f32_r"): # for B8SS
|
|
problemDict["a_type"] = "bf8_r"
|
|
problemDict["b_type"] = "f8_r"
|
|
problemDict["composite_compute_type"] = "f32"
|
|
elif (typeIndexToName[problem["DataType"]] =="b8f8" and typeIndexToName[problem["DestDataType"]]=="bf8_r"): # for B8F8B8S
|
|
problemDict["a_type"] = "bf8_r"
|
|
problemDict["b_type"] = "f8_r"
|
|
problemDict["composite_compute_type"] = "f32"
|
|
elif (typeIndexToName[problem["DataType"]] =="f8b8" and typeIndexToName[problem["DestDataType"]]=="bf8_r"): # for F8B8B8S
|
|
problemDict["a_type"] = "f8_r"
|
|
problemDict["b_type"] = "bf8_r"
|
|
problemDict["composite_compute_type"] = "f32"
|
|
else:
|
|
problemDict["composite_compute_type"] = "f32"
|
|
else:
|
|
problemDict["compute_type"] = compType
|
|
else:
|
|
if problemDict["a_type"] == "f16_r" and problem["HighPrecisionAccumulate"]:
|
|
problemDict["compute_type"] = "f32_r"
|
|
elif problem["DataType"] == 5:
|
|
problemDict["compute_type"] = "i32_r"
|
|
else:
|
|
problemDict["compute_type"] = problemDict["a_type"]
|
|
|
|
if "F32XdlMathOp" in problem and problem["F32XdlMathOp"]==9: # XF32
|
|
problemDict["math_mode"] = 1
|
|
|
|
return problemDict
|
|
|
|
def getSizeParams(size, transA, transB):
|
|
# M/N/K, batch_count, lda/b/c/d
|
|
sizeDict = {}
|
|
sizeDict["M"] = size[0]
|
|
sizeDict["N"] = size[1]
|
|
sizeDict["K"] = size[3]
|
|
|
|
if size[2] != 1:
|
|
sizeDict["batch_count"] = size[2]
|
|
# rocBLAS-bench will handle setting default strides
|
|
|
|
if len(size)==8: # ld defined in the library logic
|
|
sizeDict["ldc"] = size[4]
|
|
sizeDict["ldd"] = size[5]
|
|
sizeDict["lda"] = size[6]
|
|
sizeDict["ldb"] = size[7]
|
|
else: # no ld defined in the library logic
|
|
sizeDict["ldc"] = size[0]
|
|
sizeDict["ldd"] = size[0]
|
|
if not transA and not transB: # NN
|
|
sizeDict["lda"] = size[0]
|
|
sizeDict["ldb"] = size[3]
|
|
elif transA and not transB: # TN
|
|
sizeDict["lda"] = size[3]
|
|
sizeDict["ldb"] = size[3]
|
|
elif not transA and transB: # NT
|
|
sizeDict["lda"] = size[0]
|
|
sizeDict["ldb"] = size[1]
|
|
else: # TT
|
|
sizeDict["lda"] = size[3]
|
|
sizeDict["ldb"] = size[1]
|
|
|
|
return sizeDict
|
|
|
|
|
|
def dumpYaml(outDir, outputfile,postfix, content):
|
|
name = outputfile+postfix
|
|
benchPath = os.path.join(outDir, name)
|
|
with open(benchPath, "w") as f:
|
|
yaml.dump(content, f, yamlDumper, default_flow_style=None, sort_keys=False, width=5000)
|
|
f.write(f"# End of {name} \n")
|
|
|
|
def createYaml(args, outputfile, problem, sizeMappings, verify):
|
|
bench = []
|
|
benchStrided = []
|
|
benchGeneralBatched = []
|
|
|
|
bench_rotating = []
|
|
benchStrided_rotating = []
|
|
benchGeneralBatched_rotating = []
|
|
|
|
bench_beta0 = []
|
|
benchStrided_beta0 = []
|
|
benchGeneralBatched_beta0 = []
|
|
|
|
bench_beta0_rotating = []
|
|
benchStrided_beta0_rotating = []
|
|
benchGeneralBatched_beta0_rotating = []
|
|
|
|
bench_verify = []
|
|
benchStrided_verify = []
|
|
benchGeneralBatched_verify = []
|
|
|
|
# get GEMM function and matrix orientation - Fixed for each library
|
|
problemParams = getProblemType(problem)
|
|
transA = problem["TransposeA"]
|
|
transB = problem["TransposeB"]
|
|
|
|
# check if this is f8/b8:
|
|
f8gemm = True if (problem["DataType"]>=10) else False
|
|
|
|
if verify:
|
|
otherParams_verify = {"alpha": 1, "beta": 1, "iters": 1, "cold_iters": 0, "norm_check": 1}
|
|
|
|
#initialization
|
|
if (args.initialization=='hpl' and problemParams["a_type"]!="i8_r"):
|
|
init = {"initialization": "hpl"}
|
|
elif (args.initialization=='trig' and problemParams["a_type"]!="i8_r"):
|
|
init = {"initialization": "trig_float"}
|
|
elif args.initialization== 'int':
|
|
init = {"initialization": "rand_int"}
|
|
else:
|
|
print(f"Initialization {args.initialization} is not allowed for int8 datatype. Initialization changed to rand_int.")
|
|
init = {"initialization": "rand_int"}
|
|
|
|
# check if the library is General Batched based on the library name
|
|
generalBatched = True if "_GB.yaml" in os.path.split(args.libLogic)[-1] else False
|
|
|
|
# create rocBLAS-bench call for each size in logic file
|
|
for (size, perf) in sizeMappings: # size[0] = M, size[1] = N, size[2] = batch_count, size[3] = K, size[4] = ldc, size[5] = ldd, size[6] = lda, size[7] = ldb
|
|
|
|
params = {}
|
|
|
|
if (not generalBatched and size[2] == 1 and not f8gemm): # non-f8, non-batched gemm (serves both HPA and non-HPA)
|
|
params["rocblas_function"] = "rocblas_gemm_ex"
|
|
elif (not generalBatched and size[2] != 1 and not f8gemm): # non-f8, strided_batched gemm (serves both HPA and non-HPA)
|
|
params["rocblas_function"] = "rocblas_gemm_strided_batched_ex"
|
|
elif not generalBatched: # f8
|
|
params["rocblas_function"] = "rocblas_gemm_ex3"
|
|
elif (generalBatched and not f8gemm): # non-f8, general batched gemm (serves both HPA and non-HPA) currently there is no f8 general batched
|
|
params["rocblas_function"] = "rocblas_gemm_batched_ex"
|
|
else:
|
|
raise RuntimeError(" F8 GEMM is not supporting General Batched.")
|
|
|
|
sizeParams = getSizeParams(size, transA, transB)
|
|
|
|
if args.duration>0.0:
|
|
latency = 2*sizeParams['M']*sizeParams['N']*sizeParams['K']/perf[1]/1000 # us
|
|
latency *= sizeParams["batch_count"] if "batch_count" in sizeParams else 1
|
|
cold_iters = math.ceil( args.duration* 1e6 / latency)
|
|
iters = cold_iters
|
|
coe = 1.15
|
|
else:
|
|
cold_iters = 2
|
|
iters = 10
|
|
coe = 1
|
|
|
|
otherParams = {"alpha": 1, "beta": 1, "iters": iters, "cold_iters": cold_iters}
|
|
otherParams_rotating = {**otherParams, "flush_memory_size": 536870812}
|
|
|
|
otherParams_beta0 = {"alpha": 1, "beta": 0, "iters": math.ceil( coe * iters), "cold_iters": math.ceil( coe * cold_iters)}
|
|
otherParams_beta0_rotating = {**otherParams_beta0, "flush_memory_size": 536870812}
|
|
|
|
params.update(problemParams)
|
|
params.update(sizeParams)
|
|
params.update(init)
|
|
|
|
if (size[2] == 1 and not generalBatched):
|
|
bench.append({**params, **otherParams})
|
|
bench_rotating.append({**params, **otherParams_rotating})
|
|
bench_beta0.append({**params, **otherParams_beta0})
|
|
bench_beta0_rotating.append({**params, **otherParams_beta0_rotating})
|
|
if verify:
|
|
bench_verify.append({**params, **otherParams_verify})
|
|
|
|
elif (generalBatched):
|
|
benchGeneralBatched.append({**params, **otherParams})
|
|
benchGeneralBatched_rotating.append({**params, **otherParams_rotating})
|
|
benchGeneralBatched_beta0.append({**params, **otherParams_beta0})
|
|
benchGeneralBatched_beta0_rotating.append({**params, **otherParams_beta0_rotating})
|
|
if verify:
|
|
benchGeneralBatched_verify.append({**params, **otherParams_verify})
|
|
else:
|
|
benchStrided.append({**params, **otherParams})
|
|
benchStrided_rotating.append({**params, **otherParams_rotating})
|
|
benchStrided_beta0.append({**params, **otherParams_beta0})
|
|
benchStrided_beta0_rotating.append({**params, **otherParams_beta0_rotating})
|
|
if verify:
|
|
benchStrided_verify.append({**params, **otherParams_verify})
|
|
|
|
# write output
|
|
if len(bench) > 0:
|
|
dumpYaml(args.outDir, outputfile,"_bench.yaml", bench)
|
|
dumpYaml(args.outDir, outputfile,"_bench_beta0.yaml", bench_beta0)
|
|
dumpYaml(args.outDir, outputfile, "_bench_rotating.yaml", bench_rotating)
|
|
dumpYaml(args.outDir, outputfile, "_bench_beta0_rotating.yaml", bench_beta0_rotating)
|
|
if verify:
|
|
dumpYaml(args.outDir, outputfile, "_verify.yaml", bench_verify)
|
|
|
|
if len(benchStrided) > 0:
|
|
dumpYaml(args.outDir, outputfile, "_bench-strided.yaml", benchStrided)
|
|
dumpYaml(args.outDir, outputfile, "_bench-strided_beta0.yaml", benchStrided_beta0)
|
|
dumpYaml(args.outDir, outputfile, "_bench-strided_rotating.yaml", benchStrided_rotating)
|
|
dumpYaml(args.outDir, outputfile, "_bench-strided_beta0_rotating.yaml", benchStrided_beta0_rotating)
|
|
if verify:
|
|
dumpYaml(args.outDir, outputfile, "_verify-strided.yaml", benchStrided_verify)
|
|
|
|
if len(benchGeneralBatched) > 0:
|
|
dumpYaml(args.outDir, outputfile, "_bench-general-batched.yaml", benchGeneralBatched)
|
|
dumpYaml(args.outDir, outputfile, "_bench-general-batched_beta0.yaml", benchGeneralBatched_beta0)
|
|
dumpYaml(args.outDir, outputfile, "_bench-general-batched_rotating.yaml", benchGeneralBatched_rotating)
|
|
dumpYaml(args.outDir, outputfile, "_bench-general-batched_beta0_rotating.yaml", benchGeneralBatched_beta0_rotating)
|
|
if verify:
|
|
dumpYaml(args.outDir, outputfile, "_verify-general-batched.yaml", benchGeneralBatched_verify)
|
|
|
|
def main():
|
|
args = parseArgs()
|
|
|
|
if not (args.initialization in ['hpl', 'trig', 'int']):
|
|
raise RuntimeError(f"Initialization {args.initialization} is not allowed. Choose from hpl, trig, or int.")
|
|
|
|
for libname in os.listdir(args.libLogic):
|
|
output = os.path.splitext(libname)[0]
|
|
print(f" working on {output}")
|
|
yamlName = os.path.join(args.libLogic,libname)
|
|
with open(yamlName) as f:
|
|
logicData = yaml.load(f, yamlLoader)
|
|
|
|
try:
|
|
os.makedirs(args.outDir)
|
|
except OSError:
|
|
pass
|
|
|
|
problem = logicData[4]
|
|
sizeMappings = logicData[7]
|
|
|
|
createYaml(args, output, problem, sizeMappings, args.verify)
|
|
|
|
if __name__ == "__main__":
|
|
main()
|