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
348 lines
11 KiB
Python
Executable File
348 lines
11 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
# Copyright (c) 2022-2026 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.
|
|
|
|
import argparse
|
|
import json
|
|
import os
|
|
import re
|
|
import stat
|
|
import subprocess
|
|
import sys
|
|
|
|
|
|
def run_benchmarks(
|
|
benchmark_executables_dir,
|
|
gpu_architecture,
|
|
json_out_dir,
|
|
csv_out_dir,
|
|
benchmark_executable_filter,
|
|
skip_gathered,
|
|
size,
|
|
hot,
|
|
seed,
|
|
filter,
|
|
dry,
|
|
min_gpu_ms_per_batch,
|
|
min_secs,
|
|
noise_timeout_secs,
|
|
batch_window_size,
|
|
noise_tolerance_percent,
|
|
min_gpu_temp,
|
|
max_gpu_temp,
|
|
max_warming_secs,
|
|
max_cooling_secs,
|
|
output_batches,
|
|
spaces_per_indent,
|
|
stream_blocking_timeout_secs,
|
|
):
|
|
def is_benchmark_executable(filename):
|
|
if not re.search(benchmark_executable_filter, filename):
|
|
return False
|
|
|
|
path = os.path.join(benchmark_executables_dir, filename)
|
|
st_mode = os.stat(path).st_mode
|
|
|
|
# Return True when any execution flag is set, AND it is a regular file.
|
|
# Doesn't check permissions.
|
|
return (st_mode & (stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)) and (
|
|
st_mode & stat.S_IFREG
|
|
)
|
|
|
|
def should_skip(json_out_path):
|
|
if not skip_gathered:
|
|
return False
|
|
|
|
try:
|
|
with open(json_out_path) as f:
|
|
json.load(f)
|
|
except (FileNotFoundError, json.JSONDecodeError):
|
|
return False
|
|
|
|
return True
|
|
|
|
# Create output directories if they don't exist
|
|
os.makedirs(json_out_dir, exist_ok=True)
|
|
if csv_out_dir:
|
|
os.makedirs(csv_out_dir, exist_ok=True)
|
|
|
|
benchmark_names = [
|
|
name
|
|
for name in os.listdir(benchmark_executables_dir)
|
|
if is_benchmark_executable(name)
|
|
]
|
|
print(
|
|
"The following benchmarks will be run:\n{}".format("\n".join(benchmark_names)),
|
|
file=sys.stderr,
|
|
flush=True,
|
|
)
|
|
|
|
success = True
|
|
|
|
for benchmark_name in benchmark_names:
|
|
results_json_name = f"{benchmark_name}_{gpu_architecture}.json"
|
|
json_out_path = os.path.join(json_out_dir, results_json_name)
|
|
|
|
if should_skip(json_out_path):
|
|
print(
|
|
f"Skipping {benchmark_name}, because its results have already been gathered at {json_out_path}",
|
|
file=sys.stderr,
|
|
flush=True,
|
|
)
|
|
continue
|
|
|
|
benchmark_path = os.path.join(benchmark_executables_dir, benchmark_name)
|
|
|
|
args = [benchmark_path]
|
|
args += ["--json-out", json_out_path]
|
|
|
|
if size:
|
|
args += ["--size", size]
|
|
if hot:
|
|
args += ["--hot"]
|
|
if seed:
|
|
args += ["--seed", seed]
|
|
if csv_out_dir:
|
|
results_csv_name = f"{benchmark_name}_{gpu_architecture}.csv"
|
|
csv_out_path = os.path.join(csv_out_dir, results_csv_name)
|
|
args += ["--csv-out", csv_out_path]
|
|
if filter:
|
|
args += ["--filter", filter]
|
|
if dry:
|
|
args += ["--dry"]
|
|
if min_gpu_ms_per_batch:
|
|
args += ["--min-gpu-ms-per-batch", min_gpu_ms_per_batch]
|
|
if min_secs:
|
|
args += ["--min-secs", min_secs]
|
|
if noise_timeout_secs:
|
|
args += ["--noise-timeout-secs", noise_timeout_secs]
|
|
if batch_window_size:
|
|
args += ["--batch-window-size", batch_window_size]
|
|
if noise_tolerance_percent:
|
|
args += ["--noise-tolerance-percent", noise_tolerance_percent]
|
|
if min_gpu_temp:
|
|
args += ["--min-gpu-temp", min_gpu_temp]
|
|
if max_gpu_temp:
|
|
args += ["--max-gpu-temp", max_gpu_temp]
|
|
if max_warming_secs:
|
|
args += ["--max-warming-secs", max_warming_secs]
|
|
if max_cooling_secs:
|
|
args += ["--max-cooling-secs", max_cooling_secs]
|
|
if output_batches:
|
|
args += ["--output-batches"]
|
|
if spaces_per_indent:
|
|
args += ["--spaces-per-indent", spaces_per_indent]
|
|
if stream_blocking_timeout_secs:
|
|
args += ["--stream-blocking-timeout-secs", stream_blocking_timeout_secs]
|
|
|
|
try:
|
|
subprocess.check_call(args)
|
|
except subprocess.CalledProcessError as error:
|
|
print(
|
|
f'Could not run benchmark at {benchmark_path}. Error: "{error}"',
|
|
file=sys.stderr,
|
|
flush=True,
|
|
)
|
|
success = False
|
|
|
|
return success
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser()
|
|
|
|
# Python arguments
|
|
parser.add_argument(
|
|
"--benchmark-executables-dir",
|
|
help="Benchmark executables directory",
|
|
required=True,
|
|
)
|
|
parser.add_argument(
|
|
"--gpu-architecture",
|
|
help="Architecture of the currently enabled GPU",
|
|
required=True,
|
|
)
|
|
parser.add_argument(
|
|
"--json-out-dir",
|
|
help="Directory to write JSON result files to, creating parent directories if necessary",
|
|
required=True,
|
|
)
|
|
parser.add_argument(
|
|
"--csv-out-dir",
|
|
help="Directory to write CSV result files to, creating parent directories if necessary",
|
|
required=False,
|
|
)
|
|
parser.add_argument(
|
|
"--benchmark-executable-filter",
|
|
help="Regular expression that controls the list of benchmark executables to run",
|
|
default=r"^benchmark",
|
|
required=False,
|
|
)
|
|
parser.add_argument(
|
|
"--skip-gathered",
|
|
help="Skip running benchmarks whose JSON file has already been gathered",
|
|
default=False,
|
|
action="store_true",
|
|
required=False,
|
|
)
|
|
|
|
# primbench arguments
|
|
parser.add_argument(
|
|
"--size",
|
|
help="Input size. Benchmarks decide what this represents, but it is commonly the number of bytes or items",
|
|
default="",
|
|
required=False,
|
|
)
|
|
parser.add_argument(
|
|
"--hot",
|
|
help="Skip clearing the GPU cache between batch iterations",
|
|
default=False,
|
|
action="store_true",
|
|
required=False,
|
|
)
|
|
parser.add_argument(
|
|
"--seed", help="Seed used for input generation", default="", required=False
|
|
)
|
|
parser.add_argument(
|
|
"--filter",
|
|
help="Regex filter of specialization names to benchmark",
|
|
default="",
|
|
required=False,
|
|
)
|
|
parser.add_argument(
|
|
"--dry",
|
|
help="Perform a dry run. The benchmark setup is still run, and JSON and CSV files are still output, but state.run() immediately returns",
|
|
default=False,
|
|
action="store_true",
|
|
required=False,
|
|
)
|
|
parser.add_argument(
|
|
"--min-gpu-ms-per-batch",
|
|
help="Minimum duration of a batch in milliseconds (GPU time)",
|
|
default="",
|
|
required=False,
|
|
)
|
|
parser.add_argument(
|
|
"--min-secs",
|
|
help="Minimum total benchmark duration in seconds (wall time)",
|
|
default="",
|
|
required=False,
|
|
)
|
|
parser.add_argument(
|
|
"--noise-timeout-secs",
|
|
help="Maximum total benchmark duration in seconds before timing out a noisy run (wall time)",
|
|
default="",
|
|
required=False,
|
|
)
|
|
parser.add_argument(
|
|
"--batch-window-size",
|
|
help="Number of batch times used in the noise (coefficient of variation) window to decide early stopping",
|
|
default="",
|
|
required=False,
|
|
)
|
|
parser.add_argument(
|
|
"--noise-tolerance-percent",
|
|
help="Noise tolerance of batch times in percent, used to determine early benchmark stopping",
|
|
default="",
|
|
required=False,
|
|
)
|
|
parser.add_argument(
|
|
"--min-gpu-temp",
|
|
help="Minimum GPU temperature in °C. Too low slows benchmarks; too high increases noise",
|
|
default="",
|
|
required=False,
|
|
)
|
|
parser.add_argument(
|
|
"--max-gpu-temp",
|
|
help="Maximum GPU temperature in °C. Too low slows benchmarks; too high increases noise",
|
|
default="",
|
|
required=False,
|
|
)
|
|
parser.add_argument(
|
|
"--max-warming-secs",
|
|
help="Maximum seconds allowed for GPU warming before an error is thrown",
|
|
default="",
|
|
required=False,
|
|
)
|
|
parser.add_argument(
|
|
"--max-cooling-secs",
|
|
help="Maximum seconds allowed for GPU cooling before an error is thrown",
|
|
default="",
|
|
required=False,
|
|
)
|
|
parser.add_argument(
|
|
"--output-batches",
|
|
help="Output a `batches` array for each specialization, containing per-batch details",
|
|
default=False,
|
|
action="store_true",
|
|
required=False,
|
|
)
|
|
parser.add_argument(
|
|
"--spaces-per-indent",
|
|
help="Number of spaces per indentation level in JSON output. Set to 0 for no indentation",
|
|
default="",
|
|
required=False,
|
|
)
|
|
parser.add_argument(
|
|
"--stream-blocking-timeout-secs",
|
|
help="Maximum stream blocking duration in seconds before timing out. Stream is blocked while queueing kernel calls. Use `primbench::flags::sync` if kernel is synchronous",
|
|
default="",
|
|
required=False,
|
|
)
|
|
|
|
args = parser.parse_args()
|
|
|
|
benchmark_run_successful = run_benchmarks(
|
|
args.benchmark_executables_dir,
|
|
args.gpu_architecture,
|
|
args.json_out_dir,
|
|
args.csv_out_dir,
|
|
args.benchmark_executable_filter,
|
|
args.skip_gathered,
|
|
args.size,
|
|
args.hot,
|
|
args.seed,
|
|
args.filter,
|
|
args.dry,
|
|
args.min_gpu_ms_per_batch,
|
|
args.min_secs,
|
|
args.noise_timeout_secs,
|
|
args.batch_window_size,
|
|
args.noise_tolerance_percent,
|
|
args.min_gpu_temp,
|
|
args.max_gpu_temp,
|
|
args.max_warming_secs,
|
|
args.max_cooling_secs,
|
|
args.output_batches,
|
|
args.spaces_per_indent,
|
|
args.stream_blocking_timeout_secs,
|
|
)
|
|
|
|
return benchmark_run_successful
|
|
|
|
|
|
if __name__ == "__main__":
|
|
success = main()
|
|
if success:
|
|
exit(0)
|
|
else:
|
|
exit(1)
|