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
143 lines
6.4 KiB
C++
143 lines
6.4 KiB
C++
/*******************************************************************************
|
|
*
|
|
* Copyright (C) 2026 Advanced Micro Devices, Inc. All rights reserved.
|
|
* SPDX-License-Identifier: MIT
|
|
*
|
|
*******************************************************************************/
|
|
|
|
#include <catch2/catch_test_macros.hpp>
|
|
#include "common.hpp"
|
|
|
|
namespace {
|
|
|
|
using origami::streamk_hybrid_defaults_t;
|
|
|
|
// Builds a problem with exactly `tiles` output tiles for the given macrotile
|
|
// (a single row of `tiles` tile columns), so callers get precise control over
|
|
// the tile count fed into select_hybrid_mode's gates.
|
|
inline origami::problem_t make_problem_with_tile_count(
|
|
size_t mt_m, size_t mt_n, size_t tiles, size_t batch = 1) {
|
|
return make_problem(/*m=*/mt_m, /*n=*/mt_n * tiles, /*k=*/64,
|
|
origami::transpose_t::T, origami::transpose_t::N,
|
|
batch);
|
|
}
|
|
|
|
}
|
|
|
|
TEST_CASE("Origami streamk: select_hybrid_mode tile-count gate is inclusive of the threshold",
|
|
"[origami][streamk][hybrid]") {
|
|
// Even with a cotenant and occupancy low enough to otherwise force dynamic
|
|
// unconditionally, a grid at or below MIN_TILES_FOR_DYNAMIC stays static_.
|
|
auto hardware = make_hardware(950);
|
|
auto config = make_config(1, 1, 32, 16, 16, 16, false, 1, /*occupancy=*/1);
|
|
auto at_gate = make_problem_with_tile_count(1, 1, streamk_hybrid_defaults_t::MIN_TILES_FOR_DYNAMIC);
|
|
REQUIRE(origami::streamk::select_hybrid_mode(at_gate, hardware, config, hardware.N_CU / 2)
|
|
== origami::hybrid_mode_t::static_);
|
|
|
|
auto above_gate =
|
|
make_problem_with_tile_count(1, 1, streamk_hybrid_defaults_t::MIN_TILES_FOR_DYNAMIC + 1);
|
|
REQUIRE(origami::streamk::select_hybrid_mode(above_gate, hardware, config, hardware.N_CU / 2)
|
|
== origami::hybrid_mode_t::dynamic);
|
|
}
|
|
|
|
TEST_CASE("Origami streamk: select_hybrid_mode requires a cotenant to go dynamic",
|
|
"[origami][streamk][hybrid]") {
|
|
// Large grid and low occupancy alone aren't enough: with no cotenant
|
|
// holding any CU away from this kernel, static_ is already optimal.
|
|
auto hardware = make_hardware(950);
|
|
auto config = make_config(128, 128, 32, 16, 16, 16, false, 1, /*occupancy=*/1);
|
|
auto problem = make_problem_with_tile_count(128, 128,
|
|
streamk_hybrid_defaults_t::MIN_TILES_FOR_DYNAMIC + 1);
|
|
|
|
REQUIRE(origami::streamk::select_hybrid_mode(problem, hardware, config, /*sm_count_target=*/0)
|
|
== origami::hybrid_mode_t::static_);
|
|
REQUIRE(origami::streamk::select_hybrid_mode(
|
|
problem, hardware, config, /*sm_count_target=*/hardware.N_CU / 2)
|
|
== origami::hybrid_mode_t::dynamic);
|
|
}
|
|
|
|
TEST_CASE("Origami streamk: select_hybrid_mode low occupancy goes dynamic unconditionally",
|
|
"[origami][streamk][hybrid]") {
|
|
auto hardware = make_hardware(950);
|
|
auto problem = make_problem_with_tile_count(128, 128,
|
|
streamk_hybrid_defaults_t::MIN_TILES_FOR_DYNAMIC + 1);
|
|
|
|
for (int occupancy = 1;
|
|
occupancy <= streamk_hybrid_defaults_t::MAX_OCCUPANCY_FOR_UNCONDITIONAL_DYNAMIC;
|
|
++occupancy) {
|
|
DYNAMIC_SECTION("occupancy=" << occupancy) {
|
|
auto config = make_config(128, 128, 32, 16, 16, 16, false, 1, occupancy);
|
|
REQUIRE(origami::streamk::select_hybrid_mode(
|
|
problem, hardware, config, hardware.N_CU / 2)
|
|
== origami::hybrid_mode_t::dynamic);
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST_CASE("Origami streamk: select_hybrid_mode falls back to tiles_per_cu "
|
|
"once occupancy alone isn't decisive",
|
|
"[origami][streamk][hybrid]") {
|
|
// Occupancy above MAX_OCCUPANCY_FOR_UNCONDITIONAL_DYNAMIC, and occupancy
|
|
// reported as unknown (<= 0), both defer to the tiles_per_cu threshold.
|
|
auto hardware = make_hardware(950);
|
|
auto available_cus = hardware.N_CU / 2;
|
|
auto small = make_problem_with_tile_count(128, 128,
|
|
static_cast<size_t>(available_cus * 8.0));
|
|
auto big = make_problem_with_tile_count(128, 128,
|
|
static_cast<size_t>(available_cus * 9.0));
|
|
|
|
for (int occupancy : {0, streamk_hybrid_defaults_t::MAX_OCCUPANCY_FOR_UNCONDITIONAL_DYNAMIC + 1}) {
|
|
DYNAMIC_SECTION("occupancy=" << occupancy) {
|
|
auto config = make_config(128, 128, 32, 16, 16, 16, false, 1, occupancy);
|
|
REQUIRE(origami::streamk::select_hybrid_mode(small, hardware, config, available_cus)
|
|
== origami::hybrid_mode_t::static_);
|
|
REQUIRE(origami::streamk::select_hybrid_mode(big, hardware, config, available_cus)
|
|
== origami::hybrid_mode_t::dynamic);
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST_CASE("Origami streamk: select_hybrid_mode non-gfx950 always static",
|
|
"[origami][streamk][hybrid]") {
|
|
// Large grid, cotenant present, low occupancy: would select dynamic on
|
|
// gfx950, but the architecture guard forces static_ elsewhere.
|
|
auto config = make_config(128, 128, 32, 16, 16, 16, false, 1, /*occupancy=*/1);
|
|
auto problem = make_problem_with_tile_count(128, 128,
|
|
streamk_hybrid_defaults_t::MIN_TILES_FOR_DYNAMIC + 1);
|
|
|
|
auto hardware_gfx950 = make_hardware(950);
|
|
REQUIRE(origami::streamk::select_hybrid_mode(
|
|
problem, hardware_gfx950, config, hardware_gfx950.N_CU / 2)
|
|
== origami::hybrid_mode_t::dynamic);
|
|
|
|
auto hardware_gfx942 = make_hardware(942);
|
|
REQUIRE(origami::streamk::select_hybrid_mode(
|
|
problem, hardware_gfx942, config, hardware_gfx942.N_CU / 2)
|
|
== origami::hybrid_mode_t::static_);
|
|
}
|
|
|
|
TEST_CASE("Origami streamk: select_hybrid_mode batch multiplies tiles, crossing the gate",
|
|
"[origami][streamk][hybrid]") {
|
|
auto hardware = make_hardware(950);
|
|
auto config = make_config(128, 128, 32, 16, 16, 16, false, 1, /*occupancy=*/1);
|
|
auto base = make_problem_with_tile_count(128, 128,
|
|
streamk_hybrid_defaults_t::MIN_TILES_FOR_DYNAMIC, /*batch=*/1);
|
|
REQUIRE(origami::streamk::select_hybrid_mode(base, hardware, config, hardware.N_CU / 2)
|
|
== origami::hybrid_mode_t::static_);
|
|
|
|
auto base_b4 = base;
|
|
base_b4.batch = 4;
|
|
REQUIRE(origami::streamk::select_hybrid_mode(base_b4, hardware, config, hardware.N_CU / 2)
|
|
== origami::hybrid_mode_t::dynamic);
|
|
}
|
|
|
|
TEST_CASE("Origami streamk: select_hybrid_mode sm_count_target=0 uses N_CU",
|
|
"[origami][streamk][hybrid]") {
|
|
auto hardware = make_hardware(950);
|
|
auto config = make_config(128, 128, 32);
|
|
auto problem = make_problem(4096, 4096, 64);
|
|
auto a = origami::streamk::select_hybrid_mode(problem, hardware, config, 0);
|
|
auto b = origami::streamk::select_hybrid_mode(problem, hardware, config, hardware.N_CU);
|
|
REQUIRE(a == b);
|
|
}
|