Files
TheRock/rocm-systems/projects/rocprofiler-compute/tests/test_roofline_main.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

150 lines
5.0 KiB
Python

# Copyright (c) Advanced Micro Devices, Inc.
# SPDX-License-Identifier: MIT
"""Unit coverage for ``roofline.roofline_main``.
These tests drive ``Roofline`` directly with mocked machine specs and
self-contained temp CSVs; they never exercise the analyze CLI.
"""
import argparse
import tempfile
from pathlib import Path
import plotly.graph_objects as go
from roofline.roofline_main import Roofline
def make_run_parameters(
workload_dir: str, roofline_data_type: list[str], **extra: object
) -> dict[str, object]:
"""Build the run_parameters dict shared by the Roofline unit tests."""
run_parameters: dict[str, object] = {
"workload_dir": workload_dir,
"device_id": 0,
"sort_type": "kernels",
"mem_level": "ALL",
"is_standalone": True,
"roofline_data_type": roofline_data_type,
}
run_parameters.update(extra)
return run_parameters
class MockMspec:
"""Minimal MachineSpecs"""
def __init__(self, gpu_model: str, gpu_series: str, gpu_arch: str) -> None:
self.gpu_model = gpu_model
self.gpu_series = gpu_series
self.gpu_arch = gpu_arch
def mi200_mspec() -> MockMspec:
return MockMspec("MI210", "mi200", "gfx90a")
def make_roofline(
mspec: MockMspec,
roofline_data_type: list[str],
workload_dir: str = "",
**extra: object,
) -> Roofline:
"""Construct a Roofline for the unit tests.
Roofline never reads its ``args`` argument on the cli_generate_plot /
generate_plot paths, so a bare Namespace suffices.
"""
run_parameters = make_run_parameters(workload_dir, roofline_data_type, **extra)
return Roofline(argparse.Namespace(), mspec, run_parameters)
def write_mfma_roofline_csv(workload_dir: str) -> None:
"""Write a roofline.csv with CDNA BW + VALU + MFMA matrix columns."""
# gfx90a memory levels resolve to LDS/L1/L2/MALL.
header = [
"device",
"LDSBw",
"MALL",
"L1Bw",
"L2Bw",
"FP64Flops",
"MFMAF16Flops",
"MFMABF16Flops",
"MFMAF64Flops",
]
row = ["0", "500", "500", "500", "500", "3000", "10000", "11000", "12000"]
csv_path = Path(workload_dir) / "roofline.csv"
content = ",".join(header) + "\n" + ",".join(row) + "\n"
csv_path.write_text(content, encoding="utf-8")
def mfma_roofline_instance(workload_dir: str) -> Roofline:
return make_roofline(
mi200_mspec(),
["FP64", "BF16"],
workload_dir=workload_dir,
matrix_ops_type="MFMA",
)
def legend_names(fig: go.Figure) -> set[str]:
return {trace.name for trace in fig.data}
# =============================================================================
# cli_generate_plot early-guard returns
# =============================================================================
def test_roofline_missing_file_handling() -> None:
"""cli_generate_plot with empty ai_data returns None at the ai_data guard."""
roofline_instance = make_roofline(mi200_mspec(), ["FP32"])
result = roofline_instance.cli_generate_plot("FP32", ai_data={})
assert result is None
def test_roofline_invalid_datatype_cli() -> None:
"""cli_generate_plot with an unsupported datatype returns None."""
roofline_instance = make_roofline(mi200_mspec(), ["FP32"])
result = roofline_instance.cli_generate_plot("INVALID_DATATYPE", ai_data={})
assert result is None
# =============================================================================
# MFMA (CDNA) legend coverage
# =============================================================================
def test_generate_plot_mfma_bf16_legend() -> None:
"""BF16 on CDNA2 emits a Peak MFMA-BF16 roof and no VALU roof."""
with tempfile.TemporaryDirectory() as workload_dir:
write_mfma_roofline_csv(workload_dir)
roofline_instance = mfma_roofline_instance(workload_dir)
# Pass an existing figure so the AI overlay (which needs ai_data) is
# skipped; only the ceiling/legend traces are added.
fig = roofline_instance.generate_plot("BF16", fig=go.Figure())
names = " ".join(n for n in legend_names(fig) if n)
assert "Peak MFMA-BF16" in names, "BF16 should emit a Peak MFMA-BF16 roof"
assert "Peak WMMA-BF16" not in names, "CDNA2 path must not label roofs WMMA"
assert "Peak VALU-BF16" not in names, "BF16 is matrix-only; no VALU roof"
def test_generate_plot_mfma_fp64_dual_legend() -> None:
"""FP64 on CDNA2 emits both a Peak VALU-FP64 and a Peak MFMA-FP64 roof."""
with tempfile.TemporaryDirectory() as workload_dir:
write_mfma_roofline_csv(workload_dir)
roofline_instance = mfma_roofline_instance(workload_dir)
fig = roofline_instance.generate_plot("FP64", fig=go.Figure())
names = " ".join(n for n in legend_names(fig) if n)
assert "Peak VALU-FP64" in names, "FP64 is dual-path; expected a VALU roof"
assert "Peak MFMA-FP64" in names, "FP64 should emit a Peak MFMA-FP64 roof"
assert "Peak WMMA-FP64" not in names, "CDNA2 path must not label roofs WMMA"