Files
TheRock/rocm-libraries/projects/composablekernel/dispatcher/tests/test_codegen_common.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

245 lines
8.9 KiB
Python

#!/usr/bin/env python3
# Copyright (c) Advanced Micro Devices, Inc., or its affiliates.
# SPDX-License-Identifier: MIT
"""
Tests for codegen/codegen_common.py -- shared infrastructure for GEMM and grouped conv codegen.
Phase 1a TDD: these tests are written BEFORE the implementation exists.
Run: python3 -m pytest tests/test_codegen_common.py -v
"""
import sys
import unittest
from pathlib import Path
SCRIPT_DIR = Path(__file__).parent.resolve()
DISPATCHER_DIR = SCRIPT_DIR.parent
sys.path.insert(0, str(DISPATCHER_DIR / "codegen"))
from codegen_common import ( # noqa: E402
TileConfig,
TraitConfigBase,
CommonTypeMappings,
generate_cpp_compilation_unit,
parallel_generate,
valid_wave_configs,
valid_warp_configs,
valid_trait_configs,
needs_wave_expansion,
needs_warp_expansion,
needs_pipeline_expansion,
)
class TestTileConfig(unittest.TestCase):
"""TileConfig dataclass tests."""
def test_valid_config(self):
tc = TileConfig(128, 128, 32, 2, 2, 1, 32, 32, 16)
self.assertTrue(tc.is_valid())
def test_zero_tile_invalid(self):
tc = TileConfig(0, 128, 32, 2, 2, 1, 32, 32, 16)
self.assertFalse(tc.is_valid())
def test_non_divisible_invalid(self):
tc = TileConfig(127, 128, 32, 2, 2, 1, 32, 32, 16)
self.assertFalse(tc.is_valid())
def test_all_fields_accessible(self):
tc = TileConfig(256, 128, 64, 4, 1, 1, 32, 32, 16)
self.assertEqual(tc.tile_m, 256)
self.assertEqual(tc.tile_n, 128)
self.assertEqual(tc.tile_k, 64)
self.assertEqual(tc.warp_m, 4)
self.assertEqual(tc.warp_n, 1)
self.assertEqual(tc.warp_k, 1)
self.assertEqual(tc.warp_tile_m, 32)
self.assertEqual(tc.warp_tile_n, 32)
self.assertEqual(tc.warp_tile_k, 16)
def test_small_valid_config(self):
tc = TileConfig(16, 16, 16, 1, 1, 1, 16, 16, 16)
self.assertTrue(tc.is_valid())
class TestTraitConfigBase(unittest.TestCase):
"""TraitConfigBase dataclass tests."""
def test_valid_intrawave(self):
tc = TraitConfigBase("compv3", "cshuffle", "intrawave", False, False, False)
self.assertTrue(tc.is_valid())
def test_invalid_interwave_compv3(self):
tc = TraitConfigBase("compv3", "cshuffle", "interwave", False, False, False)
self.assertFalse(tc.is_valid())
def test_invalid_interwave_compv4(self):
tc = TraitConfigBase("compv4", "cshuffle", "interwave", False, False, False)
self.assertFalse(tc.is_valid())
def test_valid_mem_interwave(self):
tc = TraitConfigBase("mem", "cshuffle", "interwave", False, False, False)
self.assertTrue(tc.is_valid())
def test_valid_mem_intrawave(self):
tc = TraitConfigBase("mem", "cshuffle", "intrawave", False, False, False)
self.assertTrue(tc.is_valid())
def test_padding_fields(self):
tc = TraitConfigBase("compv3", "cshuffle", "intrawave", True, True, True)
self.assertTrue(tc.pad_m)
self.assertTrue(tc.pad_n)
self.assertTrue(tc.pad_k)
class TestCommonTypeMappings(unittest.TestCase):
"""CommonTypeMappings tests."""
def test_dtype_to_ck(self):
self.assertEqual(CommonTypeMappings.DTYPE_TO_CK["fp16"], "fp16_t")
self.assertEqual(CommonTypeMappings.DTYPE_TO_CK["bf16"], "bf16_t")
self.assertEqual(CommonTypeMappings.DTYPE_TO_CK["fp32"], "float")
self.assertEqual(CommonTypeMappings.DTYPE_TO_CK["fp8"], "fp8_t")
def test_pipeline_to_ck(self):
self.assertEqual(
CommonTypeMappings.PIPELINE_TO_CK["mem"], "GemmPipelineAgBgCrMem"
)
self.assertIn("compv3", CommonTypeMappings.PIPELINE_TO_CK)
self.assertIn("compv4", CommonTypeMappings.PIPELINE_TO_CK)
def test_pipeline_to_base(self):
self.assertIn("mem", CommonTypeMappings.PIPELINE_TO_BASE)
self.assertIn("compv3", CommonTypeMappings.PIPELINE_TO_BASE)
self.assertIn("compv4", CommonTypeMappings.PIPELINE_TO_BASE)
def test_scheduler_to_ck(self):
self.assertIn("intrawave", CommonTypeMappings.SCHEDULER_TO_CK)
self.assertIn("interwave", CommonTypeMappings.SCHEDULER_TO_CK)
def test_epilogue_to_dispatcher(self):
self.assertIn("cshuffle", CommonTypeMappings.EPILOGUE_TO_DISPATCHER)
self.assertIn("default", CommonTypeMappings.EPILOGUE_TO_DISPATCHER)
def test_layout_to_ck(self):
self.assertIn("r", CommonTypeMappings.LAYOUT_TO_CK)
self.assertIn("c", CommonTypeMappings.LAYOUT_TO_CK)
def test_get_output_dtype(self):
self.assertEqual(CommonTypeMappings.get_output_dtype("fp8"), "fp16")
self.assertEqual(CommonTypeMappings.get_output_dtype("bf8"), "fp16")
self.assertEqual(CommonTypeMappings.get_output_dtype("fp16"), "fp16")
self.assertEqual(CommonTypeMappings.get_output_dtype("fp32"), "fp32")
class TestGenerateCppCompilationUnit(unittest.TestCase):
"""Tests for generate_cpp_compilation_unit."""
def test_includes_kernel_header(self):
result = generate_cpp_compilation_unit("my_kernel")
self.assertIn('#include "my_kernel.hpp"', result)
def test_contains_pragma_once_or_guard(self):
result = generate_cpp_compilation_unit("test_kernel")
self.assertIn("test_kernel", result)
def test_different_names_different_output(self):
a = generate_cpp_compilation_unit("kernel_a")
b = generate_cpp_compilation_unit("kernel_b")
self.assertNotEqual(a, b)
class TestParallelGenerate(unittest.TestCase):
"""Tests for parallel_generate helper."""
def _dummy_generate(self, item):
return f"generated_{item}"
def test_parallel_returns_all(self):
items = ["a", "b", "c", "d"]
results = parallel_generate(self._dummy_generate, items, parallel=True)
self.assertEqual(len(results), 4)
for item in items:
self.assertIn(f"generated_{item}", results)
def test_sequential_returns_all(self):
items = ["x", "y", "z"]
results = parallel_generate(self._dummy_generate, items, parallel=False)
self.assertEqual(len(results), 3)
for item in items:
self.assertIn(f"generated_{item}", results)
def test_empty_items(self):
results = parallel_generate(self._dummy_generate, [], parallel=True)
self.assertEqual(len(results), 0)
def test_logs_per_kernel_progress(self):
items = ["k1", "k2"]
with self.assertLogs(level="INFO") as cm:
parallel_generate(self._dummy_generate, items, parallel=False)
log_output = "\n".join(cm.output)
self.assertIn("k1", log_output)
self.assertIn("k2", log_output)
class TestArchAwareExpansion(unittest.TestCase):
"""Tests for arch-aware expansion helpers (best-of-conv)."""
def test_valid_wave_configs_gfx942(self):
configs = valid_wave_configs("gfx942")
self.assertIsInstance(configs, list)
self.assertIn([2, 2, 1], configs)
self.assertIn([1, 4, 1], configs)
def test_valid_wave_configs_unknown_arch(self):
configs = valid_wave_configs("gfx_unknown")
self.assertIsInstance(configs, list)
self.assertGreater(len(configs), 0)
def test_valid_warp_configs_gfx942_fp16(self):
configs = valid_warp_configs("gfx942", "fp16")
self.assertIsInstance(configs, list)
self.assertIn([32, 32, 16], configs)
def test_valid_warp_configs_unknown_arch(self):
configs = valid_warp_configs("gfx_unknown", "fp16")
self.assertIsInstance(configs, list)
self.assertGreater(len(configs), 0)
def test_valid_trait_configs_excludes_interwave_compute(self):
configs = valid_trait_configs()
self.assertIsInstance(configs, list)
self.assertNotIn(("compv3", "cshuffle", "interwave"), configs)
self.assertNotIn(("compv4", "cshuffle", "interwave"), configs)
def test_valid_trait_configs_includes_mem_interwave(self):
configs = valid_trait_configs()
has_mem_interwave = any(p == "mem" and s == "interwave" for p, s in configs)
self.assertTrue(has_mem_interwave)
def test_needs_wave_expansion_wildcard(self):
self.assertTrue(needs_wave_expansion({"wave_m": -1, "wave_n": 2}))
self.assertTrue(needs_wave_expansion({"wave_m": 2, "wave_n": -1}))
def test_needs_wave_expansion_explicit(self):
self.assertFalse(needs_wave_expansion({"wave_m": 2, "wave_n": 2}))
def test_needs_warp_expansion_wildcard(self):
self.assertTrue(needs_warp_expansion({"warp_m": -1, "warp_n": 32}))
def test_needs_warp_expansion_explicit(self):
self.assertFalse(needs_warp_expansion({"warp_m": 32, "warp_n": 32}))
def test_needs_pipeline_expansion_wildcard(self):
self.assertTrue(needs_pipeline_expansion({"pipeline": "*"}))
def test_needs_pipeline_expansion_explicit(self):
self.assertFalse(needs_pipeline_expansion({"pipeline": "compv4"}))
if __name__ == "__main__":
unittest.main()