Files
rocm-systems/projects/rocprofiler-systems/tests/pytest/test_transpose.py
T
Kian Cossettini 0eac446cb0 [rocprofiler-systems] - Implement subset of CTests into PyTests (#2666)
Convert a subset of the ctest to pytest to be used in TheRock CI.
Create a new cmake flag `ROCPROFSYS_INSTALL_TESTING` to control test suite installation.
- pytest package will be installed to share/rocprofiler-systems/tests
- all compiled examples are put in share/rocprofiler-systems/examples
- all test relevant scripts are put in share/rocprofiler-systems/tests
- see README.md in share/rocprofiler-systems/tests
2026-01-26 23:10:01 -05:00

408 wiersze
10 KiB
Python

# Copyright (c) Advanced Micro Devices, Inc.
# SPDX-License-Identifier: MIT
"""
Tests for the transpose example.
Equivalent to rocprof-sys-rocm-tests.cmake
Note: MPI is not yet supported
This module tests the transpose HIP example with various instrumentation modes:
- Baseline execution (no instrumentation)
- Sampling instrumentation
- Binary rewrite instrumentation
- Runtime instrumentation
- sys-run wrapper execution
It also validates outputs including:
- Perfetto traces
- ROCpd databases
- ROCProfiler counter data
"""
from __future__ import annotations
import pytest
from pathlib import Path
pytestmark = [pytest.mark.transpose, pytest.mark.gpu]
from rocprofsys import (
GPUInfo,
)
# =============================================================================
# Transpose fixtures
# =============================================================================
@pytest.fixture
def transpose_env() -> dict[str, str]:
"""Environment variables for transpose tests."""
return {
"ROCPROFSYS_ROCM_DOMAINS": "hip_runtime_api,kernel_dispatch,memory_copy,memory_allocation,hsa_api"
}
@pytest.fixture
def rocprofiler_env(transpose_env: dict[str, str], gpu_info: GPUInfo) -> dict[str, str]:
"""Environment with ROCm events configured."""
env = transpose_env.copy()
env["ROCPROFSYS_ROCM_EVENTS"] = gpu_info.rocm_events_for_test
return env
@pytest.fixture
def transpose_rules(validation_rules_dir: Path) -> list[Path]:
"""Get validation rules files for transpose tests."""
rules_dir = validation_rules_dir / "transpose"
return [
validation_rules_dir / "default-rules.json",
rules_dir / "validation-rules.json",
rules_dir / "amd-smi-rules.json",
rules_dir / "cpu-metrics-rules.json",
rules_dir / "timer-sampling-rules.json",
rules_dir / "sdk-metrics-rules.json",
]
# ============================================================================
# Test Class: Basic Transpose Tests
# ============================================================================
class TestTranspose:
"""Basic transpose tests with all instrumentation modes."""
REWRITE_ARGS = [
"-e",
"-v",
"2",
"--print-instructions",
"-E",
"uniform_int_distribution",
]
RUNTIME_ARGS = [
"-e",
"-v",
"1",
"--label",
"file",
"line",
"return",
"args",
"-E",
"uniform_int_distribution",
]
def test_baseline(
self,
run_test,
transpose_env: dict[str, str],
assert_regex,
):
result = run_test("baseline", target="transpose", env=transpose_env, timeout=120)
assert_regex(result)
@pytest.mark.rocpd("transpose_env")
def test_sampling(
self,
run_test,
transpose_env: dict[str, str],
transpose_rules: list[Path],
assert_rocpd,
assert_perfetto,
assert_regex,
):
result = run_test("sampling", target="transpose", env=transpose_env, timeout=120)
if not result.output_dir.exists():
pytest.fail(f"Output directory not created")
assert_regex(result)
assert_perfetto(
result,
subtest_name="Perfetto HIP API Call Validation",
categories=["hip_runtime_api"],
)
assert_rocpd(result, rules_files=transpose_rules)
def test_binary_rewrite(
self,
run_test,
transpose_env: dict[str, str],
assert_perfetto,
assert_regex,
):
result = run_test(
"binary_rewrite",
target="transpose",
rewrite_args=self.REWRITE_ARGS,
env=transpose_env,
timeout=120,
)
assert_regex(result)
assert_perfetto(result)
def test_runtime_instrument(
self,
run_test,
transpose_env: dict[str, str],
assert_perfetto,
assert_regex,
):
result = run_test(
"runtime_instrument",
target="transpose",
instrument_args=self.RUNTIME_ARGS,
env=transpose_env,
timeout=480,
)
assert_regex(result)
assert_perfetto(result)
def test_sys_run(
self,
run_test,
transpose_env: dict[str, str],
assert_regex,
):
result = run_test(
"sys_run",
target="transpose",
env=transpose_env,
timeout=300,
)
assert_regex(result)
# ============================================================================
# Test Class: Two Kernels Configuration
# ============================================================================
class TestTransposeTwoKernels:
"""Test transpose with two kernels configuration (1 iteration, 2x2 size)."""
RUN_ARGS = ["1", "2", "2"]
def test_sampling(
self,
run_test,
transpose_env: dict[str, str],
assert_regex,
):
result = run_test(
"sampling",
target="transpose",
run_args=self.RUN_ARGS,
env=transpose_env,
timeout=120,
)
assert_regex(result)
def test_sys_run(
self,
run_test,
transpose_env: dict[str, str],
assert_regex,
):
result = run_test(
"sys_run",
target="transpose",
run_args=self.RUN_ARGS,
env=transpose_env,
timeout=300,
)
assert_regex(result)
# ============================================================================
# Test Class: Loop Instrumentation
# ============================================================================
@pytest.mark.loops
class TestTransposeLoops:
"""Test transpose with loop instrumentation."""
REWRITE_ARGS = [
"-e",
"-v",
"2",
"--label",
"return",
"args",
"-l",
"-i",
"8",
"-E",
"uniform_int_distribution",
]
RUN_ARGS = ["2", "100", "50"]
def test_sampling(
self,
run_test,
transpose_env: dict[str, str],
assert_regex,
):
result = run_test(
"sampling",
target="transpose",
run_args=self.RUN_ARGS,
env=transpose_env,
timeout=120,
)
assert_regex(result)
def test_binary_rewrite(
self,
run_test,
transpose_env: dict[str, str],
assert_regex,
):
result = run_test(
"binary_rewrite",
target="transpose",
rewrite_args=self.REWRITE_ARGS,
run_args=self.RUN_ARGS,
env=transpose_env,
timeout=120,
)
assert_regex(result, fail_regex=["0 instrumented loops in procedure transpose"])
# ============================================================================
# Test Class: ROCProfiler Counter Collection
# ============================================================================
@pytest.mark.rocprofiler
class TestTransposeROCProfiler:
"""Test transpose with ROCProfiler counter collection."""
REWRITE_ARGS = [
"-e",
"-v",
"2",
"-E",
"uniform_int_distribution",
]
def test_sampling(
self,
run_test,
rocprofiler_env: dict[str, str],
gpu_info: GPUInfo,
assert_perfetto,
assert_regex,
assert_file_exists,
):
result = run_test(
"sampling",
target="transpose",
env=rocprofiler_env,
timeout=120,
)
assert_regex(result)
counter_files = [result.output_dir / f for f in gpu_info.expected_counter_files]
assert_file_exists(
counter_files, subtest_name="ROCProfiler counter files existence validation"
)
assert_perfetto(
result,
subtest_name="Perfetto counter validation",
counter_names=gpu_info.counter_names,
)
def test_binary_rewrite(
self,
run_test,
rocprofiler_env: dict[str, str],
gpu_info: GPUInfo,
assert_file_exists,
assert_regex,
):
result = run_test(
"binary_rewrite",
target="transpose",
rewrite_args=self.REWRITE_ARGS,
env=rocprofiler_env,
timeout=120,
)
assert_regex(result)
counter_files = [result.output_dir / f for f in gpu_info.expected_counter_files]
assert_file_exists(
counter_files, subtest_name="ROCProfiler counter files existence validation"
)
# ============================================================================
# Parametrized Tests
# ============================================================================
class TestTransposeParametrized:
"""Parametrized tests for various transpose configurations."""
@pytest.mark.parametrize(
"iterations,tile_dim,block_rows",
[
(1, 16, 16),
(2, 32, 32),
(5, 64, 64),
],
ids=["small", "medium", "large"],
)
def test_transpose_configurations(
self,
run_test,
transpose_env: dict[str, str],
iterations: int,
tile_dim: int,
block_rows: int,
assert_regex,
):
"""Test transpose with different iteration and tile configurations."""
result = run_test(
"sampling",
target="transpose",
run_args=[str(iterations), str(tile_dim), str(block_rows)],
env=transpose_env,
timeout=120,
fail_message=f"Config ({iterations}, {tile_dim}, {block_rows}) failed",
)
assert_regex(result)
@pytest.mark.parametrize(
"runner_type,runner_kwargs",
[
("sampling", {}),
("sys_run", {}),
],
ids=["sampling", "sys-run"],
)
def test_instrumentation_modes(
self,
run_test,
transpose_env: dict[str, str],
runner_type: str,
runner_kwargs: dict,
assert_regex,
):
"""Test different instrumentation modes produce valid output."""
result = run_test(
runner_type,
target="transpose",
env=transpose_env,
timeout=120,
**runner_kwargs,
)
if not result.output_dir.exists():
pytest.fail(f"Output directory not created")
assert_regex(result)