Files
TheRock/rocm-libraries/shared/rocroller/scripts/lib/rrperf/run.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

284 lines
8.6 KiB
Python

# Copyright Advanced Micro Devices, Inc., or its affiliates.
# SPDX-License-Identifier: MIT
"""Run a benchmark suite."""
import argparse
import datetime
import importlib.util
import os
import subprocess
from dataclasses import fields
from itertools import chain
from pathlib import Path
import pandas as pd
import rrperf
import rrperf.dump_csv
import yaml
def submit_directory(suite: str, wrkdir: Path, ptsdir: Path) -> None:
"""Consolidate performance data and submit it to SOMEWHERE.
Performance data is read from .yaml files in the work directory
for the given suite. Consolidated data is written to a SOMEWHERE
directory and submitted.
"""
results = []
for jpath in wrkdir.glob(f"{suite}-*.yaml"):
results.extend(yaml.load(jpath.read_text()))
df = pd.DataFrame(results)
df.to_csv(f"{str(ptsdir)}/{suite}-benchmark.csv", index=False)
# TODO: add call to SOMEWHERE to submit
def from_token(token: str):
yield rrperf.problems.upcast_to_run(eval(token, rrperf.problems.__dict__))
def run_problems(
generator,
build_dir: Path,
work_dir: Path,
env: dict[str, str],
id_filter: list[str],
l2: bool,
) -> bool:
SOLUTION_NOT_SUPPORTED_ON_ARCH = 3
already_run = set()
result = True
failed = []
for i, problem in enumerate(generator):
if id_filter is not None and not any(
problem.id.startswith(filt) for filt in id_filter
):
continue
if problem in already_run:
continue
id = getattr(problem, "id", None)
yaml = (work_dir / f"{problem.group}-{i:06d}.yaml").resolve()
problem.set_output(yaml)
cmd = problem.command()
log = yaml.with_suffix(".log")
rr_env = {k: str(v) for k, v in env.items() if k.startswith("ROC")}
rr_env_str = " ".join([f"{k}={v}" for k, v in rr_env.items()])
if l2:
counters = str(yaml.resolve().parent / yaml.stem)
cmd = [
"rocprofv3",
"--pmc=TCC_HIT,TCC_MISS",
"--output-file=" + counters,
"--output-format=json",
"--",
] + cmd
with log.open("w") as f:
scmd = " ".join(cmd)
print(f"# env: {rr_env_str}", file=f, flush=True)
print(f"# command: {scmd}", file=f, flush=True)
print(f"# token: {repr(problem)}", file=f, flush=True)
print("running:")
print(f" id: {id}")
print(f" command: {scmd}")
print(f" wrkdir: {work_dir.resolve()}")
print(f" log: {log.resolve()}")
p = subprocess.run(cmd, stdout=f, cwd=build_dir, env=env, check=False)
status = None
if p.returncode == 0:
status = "ok"
elif p.returncode == SOLUTION_NOT_SUPPORTED_ON_ARCH:
status = "skipped (not supported on " + rrperf.utils.rocm_gfx() + ")"
else:
status = "error"
result = False
failed.append((i, problem))
print(f" status: {status}", flush=True)
already_run.add(problem)
if len(failed) > 0:
ids = [getattr(problem, "id", None) for i, problem in failed]
print("")
print(f"Failed {len(failed)} problems ids:")
print(" ".join([str(id) for id in ids]))
print("")
print(f"Failed {len(failed)} problems:")
for i, problem in failed:
cmd = list(map(str, problem.command()))
print(f"{i}: {' '.join(cmd)}")
return result
def generate_missing_attr_value(run, attr):
"""Generate value for an option missing in previous rrperf version."""
match attr:
case "workgroupMapping":
wgm_dim = getattr(run, "workgroupMappingDim")
wgm_value = getattr(run, "workgroupMappingValue")
return (wgm_dim, wgm_value)
case "matchMemoryAccess":
return True
case "unroll_x" | "unroll_y":
return 0
case "storeLDS_D":
store = getattr(run, "store")
return "LDS" in store
case "streamK":
# Old version used bool, new version uses str
streamK = getattr(run, "streamK", "None")
if isinstance(streamK, str):
return streamK != "None"
return streamK
case "streamKTwoTile":
streamK = getattr(run, "streamK", "None")
return streamK == "TwoTile"
case "streamKTwoTileDPFirst":
streamK = getattr(run, "streamK", "None")
return streamK == "TwoTileDPFirst"
case _:
raise RuntimeError(
f"Cannot handle attribute missing in previous rrperf version: {attr}"
)
def backcast(generator, build_dir):
"""Reconstruct run objects from `generator` into run objects from previous rrperf version."""
pdef = build_dir.parent / "scripts" / "lib" / "rrperf" / "problems.py"
spec = importlib.util.spec_from_file_location("problems", str(pdef))
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
for run in generator:
className = run.__class__.__name__
backClass = getattr(module, className, None)
if backClass is not None:
backObj = backClass(
**{
f.name: (
getattr(run, f.name)
if hasattr(run, f.name)
else generate_missing_attr_value(run, f.name)
)
for f in fields(backClass)
}
)
yield backObj
def get_args(parser: argparse.ArgumentParser):
common_args = [
rrperf.args.rundir,
rrperf.args.suite,
rrperf.args.id_filter,
]
for arg in common_args:
arg(parser)
parser.add_argument(
"--submit",
help="Submit results to SOMEWHERE.",
action="store_true",
default=False,
)
parser.add_argument("--token", help="Benchmark token to run.")
parser.add_argument(
"--amd_smi",
"--rocm_smi",
default="amd-smi",
help="Location of amd-smi (--rocm_smi is deprecated).",
)
parser.add_argument(
"--l2",
action="store_true",
help="Collect L2 performance counters (TCC_HIT and TCC_MISS).",
)
parser.add_argument(
"--dump_csv",
help="Dump benchmark CSV with included headers.",
action="store_true",
default=False,
)
def run(args):
"""Run benchmarks!"""
run_cli(**args.__dict__)
def run_cli( # noqa: C901
token: str = None,
suite: str = None,
submit: bool = False,
id_filter: list[str] = None,
rundir: str = None,
build_dir: str = None,
amd_smi: str = "amd-smi",
recast: bool = False,
l2: bool = False,
**kwargs,
) -> tuple[bool, Path]:
"""Run benchmarks!
Implements the CLI 'run' subcommand.
"""
if suite is None and token is None:
if rrperf.utils.rocm_gfx().startswith("gfx120"):
suite = "all_gfx120X"
else:
suite = "all"
generator = rrperf.utils.empty()
if suite is not None:
generator = chain(generator, rrperf.utils.load_suite(suite))
if token is not None:
generator = chain(generator, from_token(token))
if recast:
generator = backcast(generator, build_dir)
if build_dir is None:
build_dir = rrperf.utils.get_build_dir()
else:
build_dir = Path(build_dir)
env = dict(os.environ)
env["ROCROLLER_ENFORCE_GRAPH_CONSTRAINTS"] = "1"
env["ROCROLLER_AUDIT_CONTROL_TRACERS"] = "1"
rundir = rrperf.utils.get_work_dir(rundir, build_dir)
rundir.mkdir(parents=True, exist_ok=True)
# pts.create_git_info(str(wrkdir / "git-commit.txt"))
git_commit = rundir / "git-commit.txt"
try:
hash = rrperf.git.full_hash(build_dir)
git_commit.write_text(f"{hash}\n")
except Exception:
git_commit.write_text("NO_COMMIT\n")
# pts.create_specs_info(str(wrkdir / "machine-specs.txt"))
machine_specs = rundir / "machine-specs.txt"
machine_specs.write_text(str(rrperf.specs.get_machine_specs(0, amd_smi)) + "\n")
timestamp = rundir / "timestamp.txt"
timestamp.write_text(str(datetime.datetime.now().timestamp()) + "\n")
result = run_problems(generator, build_dir, rundir, env, id_filter, l2)
if submit:
ptsdir = rundir / "rocRoller"
ptsdir.mkdir(parents=True)
# XXX if running single token, suite might be None
submit_directory(suite, rundir, ptsdir)
if kwargs.get("dump_csv", False):
rrperf.dump_csv.dump_csv(suite, rundir)
return result, rundir