Conversation
Reapply the final Task1 Torch-owned split-K workspace and Task2 caller-resolved exact-kid interface state on top of upstream/main@a43694f1.\n\nThis is a squashed final-state review commit; obsolete intermediate Task1/Task2 implementations are intentionally not replayed. The resulting task files match the validated merge candidate.
Reapply upstream commit 1b741c0 on top of the unified public API, canonical exact-kid registry, and caller-owned Torch workspace design. Adopt the policy-tag N-D TDM API, clusterlaunch grid round-up, compile-time gfx1250 reducer dispatch, mixed-arch device guards, tuned configs, and the final decision to leave the fused family unregistered.
Reuse thread-local tensor descriptors and avoid redundant error calls so MI308 workspace performance stays within repeat noise. Record the full correctness and ABBA validation results. Co-authored-by: Cursor <cursoragent@cursor.com>
Move the architecture heuristics and tuned-candidate validation into a dedicated policy module while keeping exact execution in the family launcher. Preserve the upstream skinny-to-Torch fallback when no valid tuned row exists.
…ce_management_and_interface_refactor
…ce_management_and_interface_refactor
🏷️ CI GuideRuns automatically on every PR:
Extended tests (opt-in via labels):
PR title tags: |
| # pre-PR merge base. Keep this reference independent of policy.py. | ||
| _PRE_PR_REF = "ded4e3e8eee11f56853054c4ed4bdf2790545e5d" | ||
| _PRE_PR_HEADERS = { | ||
| "gfx950": "4c8f03542e4459b51a17c0bd9fe224533af0c594", |
Refresh the shipped OPUS parity expectations for the updated BF16 tuning rows while preserving the independent heuristic reference.
| block_n = int(instance.B_N) | ||
| block_k = int(instance.B_K) | ||
| max_useful_split_k = (K + block_k - 1) // block_k | ||
| if split_k > max_useful_split_k: |
There was a problem hiding this comment.
Could we distinguish the workspace capacity from the effective split-K count in this check?
For example, on gfx942 with BF16, (M, N, K) = (1, 64, 128), kid=10201, and split_k=0, _plan_gfx942_split_k() returns (workspace_capacity=16, abi_split_k=1). This check then compares the capacity 16 against ceil(K / B_K) = 2 and raises ValueError, even though the
effective split-K count has already been reduced to 1. Explicit split_k=1 passes planning.
Reserving more workspace than the launch needs should be safe here; the C++ validation also accepts workspace.numel() >= required_numel. Would it make sense to size the workspace using the converged split-K count, or allow this capacity overestimate while validating
the effective split-K count separately? A regression test covering automatic split-K with a short K would help keep these two steps consistent.
There was a problem hiding this comment.
The K-tile limit was incorrectly applied to workspace capacity. I moved that check into launch planning and size the gfx942 workspace from the converged split-K count. For your example, launch split-K stays 1, and planned capacity now matches it (16 slices → 1).
Verified on gfx942: auto allocation and caller workspaces with 1 or 16 slices all pass the Torch check.
Keep the exact-kid registry and caller-owned workspace interface while integrating PR ROCm#5162's FP32 partials and reducer row limit. Enforce max_m in policy, launch planning, tuning, and generated gfx1250 launchers; retain direct CO dispatch for large-M configurations. Add focused host and target-device regressions for the gfx1250 workspace contract and update source provenance for the shared OPUS dtype headers.
Restore gen_co files to the merged upstream version and remove the added provenance check, CI invocation, and dedicated test. Keep the exact-kid CO integration and its existing registry, loader, and contract coverage. Validation: 7 CPU integration tests passed; all 219 CO records match the current registry. GPU tests were not run for this tooling cleanup.
Reuse upstream cluster-launch handling and CO path define spelling. The extra JSON escaping produced the same evaluated compiler flag. Validation: 30 architecture/version gate comparisons and 7 CPU CO integration tests passed; Ruff and Black passed. No GPU tests were run.
| @@ -0,0 +1,231 @@ | |||
| # SPDX-License-Identifier: MIT | |||
| # Copyright (C) 2026, Advanced Micro Devices, Inc. All rights reserved. | |||
| """gfx1250 reducer-grid admission and FP32 workspace integration.""" | |||
There was a problem hiding this comment.
test opus_a16w16 has already covered splitk test. This file is duplicated. Also, hardcoded kid will easily failed. Remove this test will be better
Merge upstream/main at 226ee79 and reconcile transactional JIT cache publication with the exact-kid OPUS interfaces and subset code generation. Allow batched gfx1250 CO launches while retaining the batch-one restriction for workspace kernels. Remove the duplicate gfx1250 split-K test file and keep the reducer row-limit check in the existing A16 suite using registry kids. Include always-emitted MXFP8 BMM ids in compiled-kid metadata and validate extra-kid requests against the complete generated set. Validation: 1477 CPU/Meta tests and 25 subtests passed; Black, Ruff, syntax, and diff checks against upstream/main passed. No GPU tests were run.
|
gfx942 BF16-workspace exact-N guard redirects on one entry point and hard-raises on another — Problem: aiter/ops/opus/policy.py:419-425 (_resolve_a16w16_candidate) redirects kid 10210→10200 and 10213→10203 when N not in GFX942_BF16WS_EXACT_N, but aiter/ops/opus/gemm_op_a16w16.py:419-431 passes the tuned row's solidx and an explicit kernelId verbatim into _execute_a16w16, and aiter/ops/opus/launch_plan.py:285-294 then raises ValueError("gfx942 exact kid 10210 requires N in [64, 128, 256, 384, 512, 1024, 2048]; got N=1000") with no redirect anywhere in between. Impact at runtime: on a gfx942 device, gemm_a16w16_opus(A, B, kernelId=10210, splitK=2) with A: [M,K] bf16 and B: [K,1000] bf16 (N=1000, outside the exact-N set; the guard fires for any splitK) now hard-raises through the compatibility entry the author claims is behavior-preserved, where base's generated launcher (csrc/opus_gemm/codegen/gen_instances_gfx942.py:351-357 at base) silently called the fp32-workspace sibling 10200 and returned a correct Y; the tuned-row path has the same asymmetry via a user AITER_CONFIG_GEMM_BF16_FILE override (the shipped CSV carries no such rows and the base tuner already refused to emit them, so the explicit-kernelId path is the concrete trigger). Action: Author must route gemm_a16w16_opus's tuned-row and explicit-kernelId kids through resolve_a16w16_tuned_candidate (or apply the same 10210/10213 redirect inside _build_a16w16_launch_plan) so all entry points agree. [verified] |
- converge A16 split-K before workspace sizing across architectures\n- validate MXFP8 saved rows and prefetch constraints before launch\n- restore gfx942 compatibility redirects while keeping exact APIs strict\n- distinguish direct/workspace compiled-table availability\n- align gfx1250 cluster candidate and default-build coverage
Keep exhaustive heuristic, shipped-config, artifact identity, and hardware launch coverage while collapsing duplicate planner, route, compatibility, and tuner cases into their maintained owners. Validated with Black, Ruff, Python syntax checks, git diff --check, and 98 focused CPU/meta tests plus 22 subtests. GPU tests were not run locally.
Resolve the A16W16 test conflict while retaining strict exact-kid/caller-workspace coverage and main's production benchmark entry.
Keep exact-kid launch validation isolated from main's production benchmark path and remove duplicate shape-driven wrappers.
Summary
This PR refactors the OPUS GEMM/BMM around one strict, exact-kernel-id contract from Python through generated C++ dispatch.
opus_gemm()andopus_bmm()entry points,Motivation
The previous path mixed kernel selection, validation, dispatch, and workspace management across Python and C++, resulting in duplicated wrappers, heuristic dispatch, and global workspace state.
This PR defines a strict exact-kid boundary: callers select the kernel and own the output/workspace tensors, while OPUS C++ validates and launches that exact kernel.
Architecture
A16W16
A8W8
Production paths
TunedGemm.mm/gemm_a16w16()->opus_gemm()->_execute_a16w16()opus_gemm_a16w16_launch()opus_bmm()->_launch_a16w16_bmm()->_execute_a16w16()gemm_a8w8()->opus_gemm()-> A8 backendopus_gemm_a8w8_launch()gemm_a8w8_blockscale()->opus_gemm()opus_gemm_a8w8_blockscale_launch()libtype=opusrow ->opus_gemm(layout="bpreshuffle")opus_gemm_a8w8_blockscale_bpreshuffle_launch()batched_gemm_a8w8_mxscale()-> split-1 checked raw path oropus_bmm(layout="mxscale_bmm")opus_gemm_a8w8_mxscale_bmm_launch()Workspace ownership and execution
torch.compile, MetaTensor, and FakeTensor keep the registeredtorch.opspath.Current A16 two-stage workspace layouts are:
[split_capacity, batch, padded_M, padded_N][split_capacity, batch, padded_M, padded_N][split_capacity, padded_M, padded_N]The experimental gfx1250 fused split-K source remains available for repair, but it is not registered and cannot be selected by the public API.
Tuning
csrc/gemm_a16w16/gemm_a16w16_tune.py --libtype opusPerformance
All 96 eager and 96 graph cases improved. Matching device show that the gains came from Python/C ABI dispatch, not kernel changes.
Guide
aiter/ops/opus/__init__.py: strict public GEMM/BMM router and contractsaiter/ops/opus/policy.py: high-level candidate and tuned-row policyaiter/ops/opus/launch_plan.py: immutable split-K/workspace planningaiter/ops/opus/gemm_op_a16w16.py: A16 executor, Torch workspace, and C ABIaiter/ops/opus/gemm_op_a8w8.py: A8 family adapters and pybind backendcsrc/opus_gemm/opus_gemm.cu: A16/A8 GEMM family entries and exact dispatchcsrc/opus_gemm/opus_bmm.cu: MXFP8 BMM exact dispatchcsrc/opus_gemm/gen_instances.pyandcodegen/gen_instances_gfx*.py:generated manifests, subset selection, and typed exact-kid tables
csrc/opus_gemm/opus_gemm_common.py: canonical registry and family metadata