Skip to content

Add auto-config selection for fused AG+matmul with 28 tuned HBM buffer configs - #506

Closed
ryanswann-amd wants to merge 3 commits into
ROCm:mainfrom
ryanswann-amd:feature/find-highest-performing-hbm-buffer-all-gather-matm
Closed

Add auto-config selection for fused AG+matmul with 28 tuned HBM buffer configs#506
ryanswann-amd wants to merge 3 commits into
ROCm:mainfrom
ryanswann-amd:feature/find-highest-performing-hbm-buffer-all-gather-matm

Conversation

@ryanswann-amd

Copy link
Copy Markdown
Collaborator

Summary

Add an automatic configuration selection system for the fused all-gather + matmul (AG+MM) HBM buffer kernel. When config=None is passed to all_gather_matmul(), the system automatically selects the best-performing parameters for the given shape, world size, and GPU architecture.

  • 28 empirically tuned configs across ws=2/4/8 for MI300X (gfx942), from 3489 measured trials
  • Heuristic fallback for unseen shapes based on discovered parameter selection rules
  • World-size gating: ws<8 automatically falls back to PyTorch (best ws=4 result was 0.856x)
  • Nearest-shape matching for shapes close to a champion config
  • 61 unit tests covering exact match, heuristic, nearest-shape, disabled paths, and GPU arch detection

Performance (ws=8, MI300X)

Shape Label Speedup vs PyTorch TFLOPS Trials
131072×16384×16384 g2 1.34x 420.5 102
147456×28672×4096 g14 1.29x 466.5 108
327680×28672×4096 g15 1.28x 474.7 70
229376×28672×4096 g16 1.28x 471.5 124
8192×8192×262144 g5 1.22x 161.6 9
262144×8192×8192 g6 1.20x 253.0 27
16384×16384×131072 g1 1.14x 314.5 101
262144×28672×8192 g8 0.86x 442.1 72
196608×18432×16384 g9 0.85x 445.4 80
4096×14336×4096 mixtral_gate 0.70x 248.9 20
4096×11008×4096 llama7b_gate 0.55x 189.8 20
4096×4096×4096 pow2_4k 0.53x 90.9 20

World size coverage

  • ws=8: 12 shapes, 7 winners (>1x), enabled by default
  • ws=4: 9 shapes, all lose (best 0.856x), disabled — LDS overflow forces ns=1
  • ws=2: 7 shapes, all lose (best 0.887x), disabled — insufficient fetch parallelism

New/modified files

File Description
iris/ops/auto_config.py Core auto-selection module (513 lines)
iris/ops/configs/ag_mm/ 15 JSON config files organized by arch/transpose/ws
iris/ops/configs/ag_mm/regression_sizes.json Regression test shapes with expected speedups
iris/ops/all_gather_matmul.py Integration: select_ag_mm_config() when config=None
iris/ops/__init__.py Export auto_config public API
pyproject.toml + MANIFEST.in Bundle JSON configs with pip install
tests/ops/test_auto_config.py 61 unit tests

Usage

from iris.ops import all_gather_matmul

# Auto-select best config for this shape
result = all_gather_matmul(A, B)  # config=None triggers auto-selection

# Or query the config system directly
from iris.ops.auto_config import select_ag_mm_config
cfg = select_ag_mm_config(M=131072, N=16384, K=16384, world_size=8)
print(cfg.speedup)  # 1.343

Test plan

  • 61 unit tests pass (IRIS_GPU_ARCH=mi300x pytest tests/ops/test_auto_config.py)
  • All JSON configs parse and validate
  • Heuristic fallback produces valid configs for unseen shapes
  • ws<8 correctly disables and falls back to PyTorch
  • Multi-GPU integration test with torchrun (requires 8 GPUs)

Made with Cursor

ryanswann-amd and others added 3 commits April 14, 2026 02:08
Introduce iris.ops.auto_config module that automatically selects the best
kernel configuration for fused all-gather + matmul operations based on
problem dimensions (M, N, K), world size, transpose mode, and GPU
architecture.

Key changes:
- Add select_ag_mm_config() for automatic configuration lookup with
  exact match, nearest-shape fallback, and heuristic-based generation
- Add tuned JSON configs for MI300X (gfx942) across world sizes 2/4/8
  and all transpose modes (NN, NT, TN, TT), based on 3,489 measured
  trials with verified speedup data
- Integrate auto-selection into all_gather_matmul() and preamble so
  config=None uses the best known configuration automatically
- Disable iris AG+MM for ws<8 where PyTorch outperforms (ws=2 best
  0.89x, ws=4 best 0.86x) and raise RuntimeError with clear guidance
- Include 762-line test suite covering config loading, shape matching,
  heuristic generation, edge cases, and regression sizes
- Update packaging (pyproject.toml, MANIFEST.in) to include config JSONs
Expand the auto-config JSON databases with all shapes benchmarked during
the K-017/K-021 optimization campaign (3489 trials on MI300X gfx942):

ws=8: 12 shapes (was 8) — add g8, mixtral_gate, llama7b_gate, pow2_4k
ws=4: 9 shapes (was 4) — add mixtral/llama7b/pow2_4k/llama13b/llama7b_down
ws=2: 7 shapes (was 2) — add mixtral/llama7b/pow2_4k/llama13b/llama7b_down

ws=4 and ws=2 remain disabled (best 0.856x and 0.887x respectively).
Update g9 ws=8 config to match cross-validated data (gm=1, n=80 trials).
Update test to reflect pow2_4k exact match instead of heuristic fallback.

Made-with: Cursor
Copilot AI review requested due to automatic review settings April 14, 2026 15:36
@ryanswann-amd
ryanswann-amd requested a review from BKP as a code owner April 14, 2026 15:36

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds an auto-configuration selection system for fused all-gather + matmul (AG+MM), backed by tuned JSON configs and heuristic fallbacks, and integrates it into all_gather_matmul() when config=None.

Changes:

  • Introduces iris.ops.auto_config for config lookup (exact match / nearest-shape / heuristic) and GPU-arch detection.
  • Adds MI300X AG+MM config JSONs (ws=8 tuned champions; ws=2/4 disabled; TN/NT/TT heuristic defaults) plus regression size metadata.
  • Wires auto-selection into all_gather_matmul() / preamble, and adds unit tests + packaging rules to ship JSON files.

Reviewed changes

Copilot reviewed 22 out of 23 changed files in this pull request and generated 16 comments.

Show a summary per file
File Description
tests/ops/test_auto_config.py Adds CPU-only unit tests for exact match, heuristic, nearest-shape, disabled paths, and arch detection.
pyproject.toml Includes JSON config files in the built wheel via package-data.
iris/ops/configs/ag_mm/regression_sizes.json Adds regression shapes + expected speedups for validation.
iris/ops/configs/ag_mm/mi300x/NN/ws8.json Adds tuned champion configs (and measured losers) for ws=8 on MI300X.
iris/ops/configs/ag_mm/mi300x/NN/ws4.json Adds ws=4 measured data and marks ws=4 disabled.
iris/ops/configs/ag_mm/mi300x/NN/ws2.json Adds ws=2 measured data and marks ws=2 disabled.
iris/ops/configs/ag_mm/mi300x/TN/ws8.json Adds ws=8 TN heuristic defaults (no per-shape benches).
iris/ops/configs/ag_mm/mi300x/TN/ws4.json Marks ws=4 TN disabled.
iris/ops/configs/ag_mm/mi300x/TN/ws2.json Marks ws=2 TN disabled.
iris/ops/configs/ag_mm/mi300x/NT/ws8.json Adds ws=8 NT heuristic defaults (no per-shape benches).
iris/ops/configs/ag_mm/mi300x/NT/ws4.json Marks ws=4 NT disabled.
iris/ops/configs/ag_mm/mi300x/NT/ws2.json Marks ws=2 NT disabled.
iris/ops/configs/ag_mm/mi300x/TT/ws8.json Adds ws=8 TT heuristic defaults (no per-shape benches).
iris/ops/configs/ag_mm/mi300x/TT/ws4.json Marks ws=4 TT disabled.
iris/ops/configs/ag_mm/mi300x/TT/ws2.json Marks ws=2 TT disabled.
iris/ops/configs/ag_mm/default_config.json Adds global world-size gating + fallback defaults.
iris/ops/configs/ag_mm/__init__.py Marks ag_mm configs as a package for packaging/discovery.
iris/ops/configs/__init__.py Marks configs as a package for packaging/discovery.
iris/ops/auto_config.py Implements auto-selection, caching, heuristics, nearest-shape match, regression size loading.
iris/ops/all_gather_matmul.py Integrates auto-selection when config=None (currently raises if disabled).
iris/ops/__init__.py Exports auto-config API from iris.ops.
MANIFEST.in Ensures JSON config files are included in sdists.
.gitignore Attempts to unignore JSON configs under iris/ops/configs.

Comment on lines +174 to +176
M_auto, K_local_auto = A_sharded.shape
K_auto, N_auto = B.shape
world_size_auto = shmem.get_num_ranks()

Copilot AI Apr 14, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Auto-config is being selected using the local M from A_sharded.shape[0], but the config convention/tests treat M as the post-allgather (global) M (typically M_local * world_size). This will systematically pick the wrong champion/heuristic branch (e.g., bm=128 vs 256) and can materially degrade performance or select incompatible params. Use M_auto = A_sharded.shape[0] * world_size_auto (or whatever the kernel’s actual gathered-M is) when calling select_ag_mm_config().

Suggested change
M_auto, K_local_auto = A_sharded.shape
K_auto, N_auto = B.shape
world_size_auto = shmem.get_num_ranks()
M_local_auto, K_local_auto = A_sharded.shape
K_auto, N_auto = B.shape
world_size_auto = shmem.get_num_ranks()
M_auto = M_local_auto * world_size_auto

Copilot uses AI. Check for mistakes.
Comment on lines +225 to +230
if not auto_result.enabled:
raise RuntimeError(
f"iris AG+MM auto-config disabled for this shape/world_size: "
f"{auto_result.source}. Pass config=FusedConfig(...) to override, "
f"or use PyTorch all_gather + matmul instead."
)

Copilot AI Apr 14, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description says ws<8 "automatically falls back to PyTorch", but the integration currently raises RuntimeError instead of performing a fallback. This is a user-visible behavior change and also contradicts the stated design. Either (mandatory) implement the actual PyTorch fallback here (and in all_gather_matmul_preamble), or (alternative) update the PR description/docs to clearly state that the fused path raises and the caller must explicitly choose the PyTorch path.

Copilot uses AI. Check for mistakes.
Comment thread iris/ops/auto_config.py
Comment on lines +20 to +24
Transpose coverage:
The iris AG+MM kernel (`_fused_all_gather_matmul_kernel`) uses stride-based
addressing (`stride_am, stride_ak, stride_bk, stride_bn`), so transpose
layouts are handled implicitly by tensor strides. Config files exist for
all four layouts (NN, TN, NT, TT) under each architecture directory.

Copilot AI Apr 14, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The module contradicts itself about transpose support: the top-level docstring claims TN/NT/TT are supported via strides, but SUPPORTED_TRANSPOSES and its comment say NN-only and that other transposes would require kernel changes. Meanwhile, TN/NT/TT ws=8 JSON files are marked enabled: true, and select_ag_mm_config() will happily return enabled configs for those transposes. This risks callers running the fused kernel in an unsupported layout. Mandatory: make the code+configs consistent by either (A) expanding SUPPORTED_TRANSPOSES and ensuring the kernel truly supports stride-based transposes, or (B) enforcing NN-only in select_ag_mm_config() (return disabled for other transposes) and flipping TN/NT/TT ws=8 JSON enabled to false (or removing them until supported).

Copilot uses AI. Check for mistakes.
Comment thread iris/ops/auto_config.py
Comment on lines +64 to +66
# Supported transpose modes. The AG+MM kernel only supports NN layout.
# TN/NT/TT would require kernel-level changes to permute strides.
SUPPORTED_TRANSPOSES = ("NN",)

Copilot AI Apr 14, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The module contradicts itself about transpose support: the top-level docstring claims TN/NT/TT are supported via strides, but SUPPORTED_TRANSPOSES and its comment say NN-only and that other transposes would require kernel changes. Meanwhile, TN/NT/TT ws=8 JSON files are marked enabled: true, and select_ag_mm_config() will happily return enabled configs for those transposes. This risks callers running the fused kernel in an unsupported layout. Mandatory: make the code+configs consistent by either (A) expanding SUPPORTED_TRANSPOSES and ensuring the kernel truly supports stride-based transposes, or (B) enforcing NN-only in select_ag_mm_config() (return disabled for other transposes) and flipping TN/NT/TT ws=8 JSON enabled to false (or removing them until supported).

Copilot uses AI. Check for mistakes.
Comment thread iris/ops/auto_config.py
Comment on lines +82 to +84
2. rocm-smi --showproductname parsing
3. rocminfo gfx target parsing
4. Falls back to "mi300x" (most common deployment target)

Copilot AI Apr 14, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

detect_gpu_arch() docstring says it tries rocm-smi --showproductname, but the implementation only calls rocminfo. This mismatch will confuse users debugging arch detection. Update the docstring to match reality, or implement the rocm-smi path as documented.

Suggested change
2. rocm-smi --showproductname parsing
3. rocminfo gfx target parsing
4. Falls back to "mi300x" (most common deployment target)
2. rocminfo gfx target parsing
3. Falls back to "mi300x" (most common deployment target)

Copilot uses AI. Check for mistakes.
Comment on lines +395 to +396
def test_heuristic_medium_m_large_k(self):
"""M=16384, K=131072: bm=128, gm=16, kpf=16."""

Copilot AI Apr 14, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Several test docstrings/comments state incorrect expected values (e.g., kpf=1/16/4) that don’t match the assertions (kpf==8/64/8), and the g9 speedup comment says 0.950 but the config JSON has 0.854. Update these docstrings/comments so they reflect the actual behavior being tested—this will reduce confusion when future changes break the heuristic.

Copilot uses AI. Check for mistakes.
Comment on lines +405 to +406
def test_heuristic_large_m_small_k(self):
"""M=327680, K=4096: bm=256, gm=24, kpf=4."""

Copilot AI Apr 14, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Several test docstrings/comments state incorrect expected values (e.g., kpf=1/16/4) that don’t match the assertions (kpf==8/64/8), and the g9 speedup comment says 0.950 but the config JSON has 0.854. Update these docstrings/comments so they reflect the actual behavior being tested—this will reduce confusion when future changes break the heuristic.

Copilot uses AI. Check for mistakes.
Comment on lines +590 to +593
# g9 (196608x18432x16384) has speedup 0.950 — should NOT be matched
result = select_ag_mm_config(M=196608, N=18432, K=16384, world_size=8, transpose="NN", arch="mi300x")
# g9 is an exact match, but its speedup is 0.950
# The exact match path doesn't filter by speedup, but nearest does

Copilot AI Apr 14, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Several test docstrings/comments state incorrect expected values (e.g., kpf=1/16/4) that don’t match the assertions (kpf==8/64/8), and the g9 speedup comment says 0.950 but the config JSON has 0.854. Update these docstrings/comments so they reflect the actual behavior being tested—this will reduce confusion when future changes break the heuristic.

Suggested change
# g9 (196608x18432x16384) has speedup 0.950 — should NOT be matched
result = select_ag_mm_config(M=196608, N=18432, K=16384, world_size=8, transpose="NN", arch="mi300x")
# g9 is an exact match, but its speedup is 0.950
# The exact match path doesn't filter by speedup, but nearest does
# g9 (196608x18432x16384) has speedup 0.854 in the config data.
result = select_ag_mm_config(M=196608, N=18432, K=16384, world_size=8, transpose="NN", arch="mi300x")
# This call is an exact match on g9, so it is still returned even though
# nearest-shape matching would skip shapes with speedup <= 1.0.

Copilot uses AI. Check for mistakes.
Comment thread iris/ops/auto_config.py
Comment on lines +58 to +59
# In-memory cache: (arch, transpose, world_size) -> loaded JSON data
_config_cache: Dict[Tuple[str, str, int], dict] = {}

Copilot AI Apr 14, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_config_cache is annotated as storing dict values but the implementation stores None for a non-existent config file. Adjust the type to Dict[Tuple[str, str, int], Optional[dict]] (or avoid caching missing entries as None) to keep type hints accurate and prevent downstream type-checker issues.

Suggested change
# In-memory cache: (arch, transpose, world_size) -> loaded JSON data
_config_cache: Dict[Tuple[str, str, int], dict] = {}
# In-memory cache: (arch, transpose, world_size) -> loaded JSON data or None
_config_cache: Dict[Tuple[str, str, int], Optional[dict]] = {}

Copilot uses AI. Check for mistakes.
Comment thread iris/ops/auto_config.py
Comment on lines +179 to +180
_config_cache[cache_key] = None
return None

Copilot AI Apr 14, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_config_cache is annotated as storing dict values but the implementation stores None for a non-existent config file. Adjust the type to Dict[Tuple[str, str, int], Optional[dict]] (or avoid caching missing entries as None) to keep type hints accurate and prevent downstream type-checker issues.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants