Repository navigation
feat(rocke): channel-packed and large-filter depthwise dgrad - #14386
Conversation
Depthwise dgrad on wave32 ran one channel per lane with 16-bit loads and stores and scalar FMAs, and had no kernel at all for filters past 11x11 or for the non-square SLaK filters. - DirectDepthwiseDgradStreamSpec.cpl (2, 4, 8): every lane owns cpl adjacent channels; dY and dX move as one vector per lane and the taps run as packed <2 x f32> FMAs over channel pairs. cpl == 1 emits the unchanged kernel. A validator bound keeps the packed weights and accumulators out of scratch. - DirectDepthwiseTiledSpec.dgrad: a stride-1 depthwise dgrad is the forward correlation of dY with the filter rotated by 180 degrees at padding K-1-P, so the output-stationary forward kernel serves it through the dgrad kernarg block. New AOT variant direct_depthwise_tiled_dgrad for 13x13 .. 31x31 and 51x5 / 5x51. - DirectConvProblem.pad_w / DirectCaps.kw, pad_w: per-axis padding and non-square filters for that variant only; every other variant is refused such a problem, and the benchmark accepts -p != -q only for a stride-1 depthwise dgrad. - AOT: cpl knobs for direct_depthwise_dgrad, the new variant's caps and knobs. Tests: library/tests/test_direct_depthwise_dgrad_v2.py (validators, AOT grid entries, the padding gate, gfx1250 numerics against torch). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The C++ engine builds the channel-packed and large-filter depthwise dgrad
kernels byte for byte like the Python builders:
- rocke_direct_depthwise_dgrad_stream_spec_t ports
DirectDepthwiseDgradStreamSpec, which the engine did not cover yet: spec
defaults, block_ch, kernel name, validate / is_valid (including the cpl
rules: 1, 2, 4 or 8, groups % cpl == 0, the packed weight and accumulator
bounds), the scalar ho-streaming builder and its cpl > 1 form with
cpl-wide vector I/O and packed <2 x f32> FMAs. New files
conv_direct_grouped_build_depthwise_dgrad_stream.cpp and
rocke/instance_conv_direct_grouped_dw_dgrad.h.
- rocke_direct_depthwise_tiled_spec_t gains dgrad: the dgrad kernarg block
with the extents swapped, the rotated weight rows, padding KH-1-PAD /
KW-1-PAD_W, dX addressed through its strides; the "dg" name flag, filters
up to 64 on a side in that mode, and the padding checks of validate().
- rocke_direct_conv_problem_t gains pad_w (-1: PAD) and
rocke_direct_conv_problem_pad_w; every C++ mirror of DirectConvProblem.Wo
uses it, as the Python property does.
- Parity: conv_direct_grouped_emit.{py,c} configs 171-188 (scalar and cpl
2 / 4 / 8 streaming dgrad, fp16 and bf16, stride 1 and 2, wave32 and
wave64; tiled dgrad 13x13, 31x31, 51x5, 5x51 and a per-axis padding; six
specs both engines reject).
- Golden: five gfx1250 cases in the representative IR harness (new keys
only; existing hashes unchanged).
- CTest runs test_direct_depthwise_dgrad_v2.py; convolution.md, index.md and
SUPPORT_MATRIX.md describe the streaming dgrad, cpl and the dgrad mode.
The depthwise kinds have no pybind route, so the parity pair is the
cross-engine gate.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
✅ All Checks Passed — Ready for Review
📖 Need help? See the Policy FAQ for details on every check and how to fix failures. |
|
🎉 All checks passed! This PR is ready for review. |
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved error-path safety and asymmetric-padding correctness issues prevent approval.
4 open issues
What changed in this PR
Extends rocKE’s direct-convolution kernels with channel-packed depthwise backward-data computation and support for large, non-square filters. The new configurations use the ahead-of-time (AOT) cache; dispatcher wiring remains out of scope.
Changes:
- Adds packed row-streaming and rotated-filter tiled dgrad kernels, with matching C++ implementations.
- Extends per-axis padding, launch geometry, and AOT identities and configurations.
- Adds numerical tests, cross-engine parity cases, golden IR entries, and documentation.
Paths below are relative to dnn-providers/hip-kernel-provider/rocke/.
| File | Description |
|---|---|
platform/tests/instances/rocke_ir_parity_harness.py |
Registers five representative dgrad cases. |
platform/tests/golden/rocke_representative_ir_sha256.json |
Adds hashes across three LLVM flavors. |
platform/python/rocke/instances/SUPPORT_MATRIX.md |
Documents both dgrad variants and constraints. |
platform/dsl_docs/instances/index.md |
Lists the extended depthwise specs. |
platform/dsl_docs/instances/convolution.md |
Describes packing, rotated filters, and padding. |
platform/cpp/instances/common/conv_direct_nongrouped.cpp |
Uses effective column padding for output width. |
platform/cpp/instances/common/conv_direct_grouped_spec_and_validate.cpp |
Extends defaults, naming, and tiled validation. |
platform/cpp/instances/common/conv_direct_grouped_build_depthwise.cpp |
Updates depthwise output-width calculation. |
platform/cpp/instances/common/conv_direct_grouped_build_depthwise_tiled.cpp |
Implements rotated-filter dgrad emission. |
platform/cpp/instances/common/conv_direct_grouped_build_depthwise_spatial.cpp |
Updates spatial output-width calculation. |
platform/cpp/instances/common/conv_direct_grouped_build_depthwise_dgrad_win.cpp |
Uses column padding in geometry validation. |
platform/cpp/instances/common/conv_direct_grouped_build_depthwise_dgrad_stream.cpp |
Adds scalar and packed streaming builders and helpers. |
platform/cpp/include/rocke/instance_conv_direct_wgrad_internal.hpp |
Updates shared wgrad output-width calculation. |
platform/cpp/include/rocke/instance_conv_direct_grouped.h |
Exposes column padding and tiled dgrad fields. |
platform/cpp/include/rocke/instance_conv_direct_grouped_dw_dgrad.h |
Declares streaming dgrad APIs and bounds. |
platform/CMakeLists.txt |
Registers the new numerical test suite. |
library/tests/test_direct_kernel_cache.py |
Restricts forward expectations to forward variants. |
library/tests/test_direct_depthwise_dgrad_v2.py |
Tests validation, AOT entries, and GPU numerics. |
library/tests/parity/conv_direct_grouped_emit.py |
Adds Python parity and rejection cases. |
library/tests/parity/conv_direct_grouped_emit.c |
Adds matching C++ parity cases. |
library/kernels/conv/kernel_identity.py |
Matches effective column padding. |
library/kernels/conv/direct_variants.py |
Registers tiled dgrad and padding gates. |
library/kernels/conv/direct_aot_jobs.py |
Adds packed configurations and large-filter capabilities. |
library/kernels/common/conv_direct_grouped.py |
Implements packing, tiled dgrad, and launch geometry. |
library/kernels/common/conv_args.py |
Passes effective column padding into launch arguments. |
library/benchmarks/common/benchmark_direct_conv.py |
Accepts per-axis padding for depthwise dgrad requests. |
Review effort: Balanced
- Name a per-axis padding in DirectDepthwiseTiledSpec kernel names: specs
that differ only in pad_w bake different column offsets, so the name
gains a p{PAD}x{PAD_W} part when PAD_W != PAD. Names with one padding
for both axes are unchanged. Re-bless the one golden case it renames.
- Only -1 is the pad_w sentinel: the tiled spec (both modes), the
row-streaming dgrad spec and direct_spec_for_problem refuse values
below -1 instead of reading them as PAD.
- The row-streaming dgrad kernel offsets columns by PAD, so its
validators refuse a problem whose PAD_W != PAD.
- rocke_direct_depthwise_dgrad_stream_lower_to_llvm zero-initialises its
builder: when the kernel name overflows, _new() fails before
rocke_ir_builder_init and the failure path reads and frees the builder.
Both engines change alike. Parity configs 189-192 add a per-axis-padded
tiled dgrad spec and three specs both engines reject. A host-only C++ test
covers the name overflow path, the refusals and the kernel name.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
parse_miopen_cmd_direct admits a per-axis padding for a stride-1 depthwise dgrad, which only the rotated-filter tiled kernel computes and only --run-from-cache serves. The uncached sweep builds the row-streaming kernel, which offsets columns by PAD, so it now skips such a case with a pointer to --run-from-cache (and returns 2 when no case is left). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Automated review: Model - qwen3.6:35b-a3b-coding-mtp-q4_K_M, effort: max PR #14386 — channel-packed and large-filter depthwise dgrad — 🟠 First-round: closer look recommended — byte-identical in both engines, and all 10 numeric cases pass on a gfx1151 GPU, but CI checks none of the new kernels' numerics, which also ship to gfx942 / gfx950
The worker's one item is dropped. It doubted that a zero-initialized builder can be freed, but Utility: 🟢 Positive — packs channels into the row-streaming depthwise dgrad (vector loads and packed FMAs), and serves depthwise dgrad filters up to 64 a side, including non-square ones, through the rotated-filter mode. Legend: 🔴 blocking · 🟠 should-fix · 🟡 minor nit · 🟢 info/good · ⚪ retracted First-round review: a local qwen3.6 model made the independent first pass. The orchestrator (Claude Opus 5.5) verified it. On a merge with today's develop the checks covered the native build and ctests, byte identity at three flavors, the golden gate and the direct-conv CPU suites against develop. They also included the PR's numeric cases on a gfx1151 GPU, a count of the AOT grid's new jobs per arch, a check of which arches the new specs validate on, and the CI state at head. The orchestrator owns this merge-worthiness call. It flags whether a closer look is needed; it is not an approval or a rejection. |
aledudek
left a comment
There was a problem hiding this comment.
Added 2 comments, overall LGTM
Resolve the representative IR golden conflict by keeping both sides' cases and recomputing each flavor's summary counts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… run its GPU test on every arch The cpl > 1 validity bounds (cpl * KH * KW <= 200, cpl * block_w * KH <= 192) let through binaries that spill: compiling the packed grid, a third of the gfx950 entries spill to scratch (all of cpl 2 on 9x9, cpl 4 on 7x7, cpl 8 on 5x5) and about half of the gfx1151 / gfx1201 ones do. Add an arch-aware policy gate to the AOT grid (_dw_dgrad_packed_spills), calibrated on the compiled grid: per lane cpl * KH * (2 * KW + block_w / stride) <= 288, and on gfx1250, which spills only in four-wave blocks, <= 448 there. The gfx942 / gfx950 entries it drops all overflow the 256 architectural VGPRs; what it keeps spills at most a few registers on a handful of entries. Validity is unchanged, so the C++ engine and the IR are untouched; the bound comments in both engines and the docs now say they are ceilings, not a spill model. The GPU numerics test no longer needs gfx1250 and torch: it builds each case at the running arch's wave size, skips a case the arch refuses, and checks against a numpy reference, so wave64 CI lanes exercise the kernels too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ke/gfx1250-dgrad-depthwise Regenerate the IR golden after merging develop (#14349). This also refreshes stale kernel_name/bytes metadata for conv_direct_depthwise_tiled/gfx1250/dgrad_fp16_k51x5_w32 (missing the _p25x2 padding suffix); its IR sha256 is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
I reviewed this PR again. The following review threads are still unresolved, or comments have no author reply: If you have already fixed these, please reply on each comment to say so and resolve the threads. |
|
@cgmillette re N1 (CI never checks the new kernels' numerics): addressed in 8b07304. @CongMa13 this was the only open item from your list; replied here, no further changes needed. |
No textual conflicts (platform/CMakeLists.txt auto-merged). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ferential golden Record the new conv_direct_grouped parity configs 171..192 (13 that both engines emit; the reject-only specs carry no hash) in llvm_gfx_all.json for ll[llvm20/llvm22/llvm23] and ir_canonical, via run_diff.py --python-only --record-golden --only conv_direct_grouped. Additions only; no existing hash changed or removed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ke/gfx1250-dgrad-depthwise Golden summary counters recomputed from the merged cases. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ad-depthwise' into users/jakpiase/rocke/gfx1250-dgrad-depthwise
|
@CongMa13 re your 10-27 note pointing at #14386 (comment) (N1, "CI never checks these kernels' numerics"): this was answered in #14386 (comment) and fixed in 8b07304. Re-verified after merging today's develop (48bba2a): the test passes on gfx1250 (11 passed, 10 GPU subtests); byte identity ( |
|
Automated review: Model - qwen3.6:35b-a3b-coding-mtp-q4_K_M, effort: max PR #14386 — channel-packed and large-filter depthwise dgrad (jakpiase, AICK-2337) — 🟢 Follow-up: all prior items fixed — the numeric cases now run and pass in CI on gfx942 and gfx110X, and the AOT grid drops the spilling channel-packed entries
Net-new: none. Utility: 🟢 Positive — channel-packed and large-filter depthwise dgrad, with numerics now checked in CI. Legend: 🔴 blocking · 🟠 should-fix · 🟡 minor nit · 🟢 info/good · ⚪ retracted Follow-up review: a local qwen3.6 model made the independent first pass. The orchestrator (Claude Opus 5.5) verified it. The checks were an interdiff of the PR's own change since the head we reviewed ( |
…ke/gfx1250-dgrad-depthwise Conflict only in the representative golden's summary counters (develop added conv_wgrad/gfx1250/n1h8c16k32r3_spk4, this branch adds 5 gfx1250 depthwise-dgrad cases); counters recomputed from the merged cases: ok_cases 310/310/318, gfx1250 32/32/40. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Merged current
Checks on the merge (CPU only):
No GPU tests were run for this merge. |
Develop brought #14392 (channel-packed depthwise forward), which also extends DirectDepthwiseTiledSpec and the wave32 parity block. - DirectDepthwiseTiledSpec (Python and C++): keep both new fields, dgrad and cpl. The kernel name carries the per-axis padding part, the cpl part and the ur/dg/bf16 flags. The rotated-filter dgrad mode packs one channel per lane, so both engines now refuse dgrad with cpl > 1 (Python and host tests added). - conv_direct_grouped parity: develop's wave32 configs end at 178, so this branch's depthwise dgrad configs move from 171..192 to 179..200. The differential golden's entries move with them, hashes unchanged; docs and the harness comment follow. - direct_aot_jobs imports, test_direct_kernel_cache wave32 test: union. - Representative golden re-blessed; every case hash equals develop's or this branch's. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Merged current Conflicts and resolution:
Checks on the merge (CPU only):
|
|
Automated review: Model - qwen3.6:35b-a3b-coding-mtp-q4_K_M, effort: max PR #14386 — channel-packed and large-filter depthwise dgrad (jakpiase, AICK-2337) — 🟡 Follow-up: merge verified, minor padding gap
Utility: 🟢 Positive — channel-packed and large-filter depthwise dgrad, both engines, merged cleanly with #14392. Legend: 🔴 blocking · 🟠 should-fix · 🟡 minor nit · 🟢 info/good · ⚪ retracted Follow-up review: a local qwen3.6 model made the independent first pass. The orchestrator (Claude Opus 5.5) verified it. The checks were an interdiff and a remerge-diff of the PR's own change since the head we reviewed ( |
Brings in #14385 (strided, dilated and packed-group WMMA direct dgrad). The only conflict was the summary counters of the representative golden; re-blessed with --write, and every case hash equals develop's or this branch's. Develop adds no conv_direct_grouped parity configs and does not touch the differential golden, so this PR's configs keep 179-200. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
DirectConvProblem.pad_w, added by this PR, makes p.Wo follow PAD_W, but the WMMA forward (direct, small C, small K) and dgrad kernels offset columns by PAD and their C++ mirrors size Wo from PAD. With PAD_W != PAD their validators passed and built another convolution, and the engines disagreed on Wo. Only direct_spec_for_problem refused it. Move the row-streaming dgrad's padding check into one_padding_reason (Python) / rocke_direct_conv_one_padding_reason (C++) and apply it in wmma_fwd_gate and in the dgrad WMMA validator, in both engines, with the same message. Covered in test_direct_depthwise_dgrad_v2.py and in the rocke_conv_direct_dw_dgrad_host ctest, which is now listed in the quick and ffm-quick CTest categories so CI runs it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Automated review: Model - qwen3.6:35b-a3b-coding-mtp-q4_K_M, effort: max PR #14386 — channel-packed and large-filter depthwise dgrad (jakpiase, AICK-2337) — 🟢 Follow-up: WMMA padding fix verified
Net-new: none. Utility: 🟢 Positive — channel-packed and large-filter depthwise dgrad in both engines; WMMA padding gap closed. Legend: 🔴 blocking · 🟠 should-fix · 🟡 minor nit · 🟢 info/good · ⚪ retracted Follow-up review: a local qwen3.6 model made the independent first pass. The orchestrator (Claude Opus 5.5) verified it. The checks were an interdiff and a remerge-diff of the PR's own change since the head we reviewed ( |
Conflict: summary counters of the representative IR golden. Develop added 2 gfx942 cases and this branch 5 gfx1250 cases; the counters are recomputed from the merged cases (ok_cases 314 / 314 / 338). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brings #14387 (wave32 WMMA stem dgrad). The only conflict was the llvm23 summary counters of the representative IR golden: develop added 4 stem-dgrad cases and this branch 5 depthwise-dgrad cases. Cases and expected failures are the union of both sides with their hashes; the summary counters are recomputed from them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#14387's dgrad_patch_wmma and dgrad_smallc_wmma take a DirectConvProblem and offset columns by PAD, so like the other WMMA convolutions their validators now refuse PAD_W != PAD and pad_w < -1, through the shared one_padding_reason / rocke_direct_conv_one_padding_reason, in both engines. The check follows each kernel's PAD check. Emitted IR is unchanged. The pytest and rocke_conv_direct_dw_dgrad_host cases cover both kernels. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Automated review: Model - qwen3.6:35b-a3b-coding-mtp-q4_K_M, effort: max PR #14386 — channel-packed and large-filter depthwise dgrad (jakpiase, AICK-2337) — 🟢 Follow-up: golden conflict resolved exactly
Net-new: none. Utility: 🟢 Positive — channel-packed and large-filter depthwise dgrad in both engines; per-axis padding refused elsewhere. Legend: 🔴 blocking · 🟠 should-fix · 🟡 minor nit · 🟢 info/good · ⚪ retracted Follow-up review: a local qwen3.6 model made the independent first pass, and the orchestrator (Claude Opus 5.5) verified it. The checks were a range-diff and remerge-diffs since the head we reviewed ( |
Brings in #14393 (gfx1250 split-K forward conv) and #14379 (conv sweep benchmarks). Only the representative IR golden conflicted, on its summary counters: develop's split-K cases and this branch's five depthwise dgrad cases per flavor do not overlap. Merged case by case against the merge base, with the counters recomputed from the merged cases. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The direct predicate reads the column padding as PAD_W, which pad_w overrides, but DIRECT_PROBLEM_CAPABILITY_ATTRS from #14379 left pad_w out. Two problems differing only in pad_w then shared a capability key, so a cache filter could answer a per-axis padding with the verdict for an equal one. test_direct_problem_key_covers_every_extent_the_predicate_reads caught it after the merge; a new test pins the separation directly. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Automated review: Model - qwen3.6:35b-a3b-coding-mtp-q4_K_M, effort: max PR #14386 — channel-packed and large-filter depthwise dgrad (jakpiase, AICK-2337) — 🟠 Follow-up: conflicts with #14494, re-merge needed
Utility: 🟢 Positive — channel-packed, large-filter depthwise dgrad in both engines; cache key covers column padding. Legend: 🔴 blocking · 🟠 should-fix · 🟡 minor nit · 🟢 info/good · ⚪ retracted Follow-up review: a local qwen3.6 model made the independent first pass, and the orchestrator (Claude Opus 5.5) verified it. The checks were an interdiff and a remerge-diff since the head we reviewed ( |
|
Automated merge-queue status (rocKE merge monitor) Hi @jakpiase, I turned auto-merge off on this PR for now. Before a rocKE PR lands, the rocKE merge monitor checks it on top of today's develop branch, and this version would not land cleanly:
The open items from our review, each with its fix:
What to do: address the open items in our latest review (#14386 (comment)). After that, turn auto-merge back on; the monitor re-checks every push. Nothing else changed: the monitor does not approve, reject or merge PRs. It only turned auto-merge off to keep develop green. This comment is updated in place. |
#14494 moved every C++ test registration out of platform/tests/CMakeLists.txt into tests/cmake/*.cmake, which made this branch's rocke_conv_direct_dw_dgrad_host block the merge's only conflict. CMakeLists.txt is now develop's orchestrator unchanged, and the block moves verbatim (re-indented to file scope) into cmake/InstanceTests.cmake, between the same two neighbours it sat between before. Its YAML tier entries are unchanged and still apply, since the labels run after InstanceTests.cmake. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#14679 split the representative-IR golden into per-family shards under platform/tests/golden/rocke_representative_ir_sha256/ and deleted the single file this branch had added cases to. The old file goes; this branch's delta against the merge base (5 cases per flavor, no other change) is applied to the conv_direct and conv_direct_depthwise_tiled shards with their hashes unchanged, written the way the harness writes a shard. The shards differ from develop's by those additions only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Automated review: Model - qwen3.6:35b-a3b-coding-mtp-q4_K_M, effort: max PR #14386 — channel-packed and large-filter depthwise dgrad (jakpiase, AICK-2337) — 🟡 Follow-up: re-merge verified, CI running
Net-new: none. Utility: 🟢 Positive — channel-packed, large-filter depthwise dgrad in both engines; follows develop's new layouts. Legend: 🔴 blocking · 🟠 should-fix · 🟡 minor nit · 🟢 info/good · ⚪ retracted Follow-up review: first pass by a local qwen3.6 model, verified by the orchestrator (Claude Opus 5.5). Checks: merge with develop, build + ctest, byte identity, library parity, representative and differential goldens, PR tests, compile, rules 1–3, #14494's registration test, interdiff and remerge-diffs since |
TheRock Submodule Bump ActivityNewest first
|


Motivation
On wave32 targets, the row-streaming depthwise dgrad (
DirectDepthwiseDgradStreamSpec, AOT variantdirect_depthwise_dgrad) runs one channel per lane. It uses 16-bit loads and stores and scalar FMAs. Depthwise dgrad also has no direct kernel for filters past 11x11 or for non-square decomposed large kernels (51x5 / 5x51), so those layers fall back to implicit GEMM.This PR does three things:
Like
conv_direct_dgrad_wmma, the new binaries are served by the direct-conv AOT cache. There is no dispatcher wiring.JIRA ID: AICK-2337
Technical Details
Channel-packed row-streaming dgrad (
DirectDepthwiseDgradStreamSpec.cpl,library/kernels/common/conv_direct_grouped.py)cpl2, 4 or 8, every lane ownscpladjacent channels:cpl-wide vector per lane;cpl / 2packed<2 x f32>FMAs over channel pairs.stride * KHcircular accumulator slots with a few rows prefetched, and a tail loop flushes the rows past the last dY row.cpl == 1emits the unchanged kernel.cplin {1, 2, 4, 8} andgroups % cpl == 0;cpl * KH * KW <= 200for the packed weights;cpl * block_w * KH <= 192for the accumulator slots.block_chgrows bycpl, and the kernel name gainscpl{N}.Rotated-filter dgrad (
DirectDepthwiseTiledSpec.dgrad)KH-1-PADrows andKW-1-PAD_Wcolumns.ris read from rowKH-1-r, reversed;H x W.dgflag.dgrad=Falseemits the unchanged kernel.dgradwithcpl > 1(the forward mode's channel-packed kernel, from feat(rocke): wave32 WMMA direct and small-channel forward convolution for gfx1250 #14392, is forward only).Per-axis padding (
DirectConvProblem.pad_w)pad_w = -1meansPAD.PAD_Wis the effective column padding, andWouses it.PAD_W != PAD:direct_fwd_wmma,fwd_smallc_wmma,fwd_smallk_wmmathroughwmma_fwd_gate,direct_dgrad_wmma, and feat(rocke): wave32 WMMA stem dgrad for gfx1250 (patch embeddings, small-C stems) #14387's stem dgrad kernelsdgrad_patch_wmmaanddgrad_smallc_wmma) refuse one in their validators, in both engines. They offset columns byPAD. The check isone_padding_reason/rocke_direct_conv_one_padding_reason, shared with the row-streaming dgrad;direct_spec_for_problemrefuses one for every other variant;direct_job_for_identitybuilds non-square / per-axis identities only for the new variant.kernel_identitymatchespad_wagainstPAD_W, andconv_argspassespW = PAD_W.DIRECT_PROBLEM_CAPABILITY_ATTRS, from feat(rocke): improve conv sweep benchmarks #14379) includespad_w, so problems that differ only in their column padding never share a cached support verdict.-p != -qonly for a stride-1 depthwise dgrad.AOT (
library/kernels/conv/direct_variants.py,direct_aot_jobs.py)direct_depthwise_dgradgains theDW_DGRAD_CPL_GRIDknobs. Thecpl == 1knobs keep their identities.direct_depthwise_tiled_dgrad, inDIRECT_WAVE_PARAMETRIC:DW_TILED_DGRAD_BLOCK_WxDW_TILED_DGRAD_BLOCK_H.DirectCapsgainskw/pad_wfor those rows.C++ engine
rocke/instance_conv_direct_grouped_dw_dgrad.handconv_direct_grouped_build_depthwise_dgrad_stream.cppportDirectDepthwiseDgradStreamSpec. This covers the defaults,block_ch, the kernel name,validate/is_valid(same order and reason text as Python), and the scalar andcpl > 1builders. They also add_newandlower_to_llvmentries.rocke_direct_depthwise_tiled_spec_t.dgradcovers the builder mode, thedgname flag, the dgrad filter limit and the padding checks ofvalidate().rocke_direct_conv_problem_t.pad_w(default -1),rocke_direct_conv_problem_pad_wandrocke_direct_conv_one_padding_reason. Every C++ mirror ofDirectConvProblem.Woin the direct-conv family uses it, as the Python property does.rocke_enginebinding, here or ondevelop. The parity pair is the cross-engine gate.Docs:
dsl_docs/instances/convolution.md(the dgrad mode in the tiled section, and a new row-streaming depthwise dgrad section),dsl_docs/instances/index.md,SUPPORT_MATRIX.md.Test Plan
check_byte_identity.py, all families, at llvm20, llvm22 and llvm23.conv_direct_grouped_emit.{py,c}parity configs 179-200 (after develop's wave32 forward configs 166-178):cpl2 / 4 / 8, in fp16 and bf16, at stride 1 and 2, on wave32 (gfx1250) and wave64 (gfx950);pad_w), 5x51 (pad_w, unrolled rows), a 7x7 with a padding that differs per axis and is not "same", and a 5x5 withpad_w = 0(the kernel name carries the per-axis padding);groups % cpl != 0;cpl = 3;pad_w < -1on the rotated-filter dgrad;pad_w < -1on the row-streaming kernel.tests/instances/differential/golden/llvm_gfx_all.json): the newconv_direct_groupedconfigs that both engines emit are blessed forll(llvm20 / llvm22 / llvm23) andir_canonical.cpl2,cpl8 stride 2 bf16; rotated-filter 31x31 and 51x5) at every flavor.library/tests/test_direct_depthwise_dgrad_v2.py, now in CTest: validators, AOT grid entries (including the packed-entry spill gate), the padding gate, and numerics against a numpy reference on any arch rocke models (each case built at the arch's wave size; cases the arch's validator refuses are skipped).rocke_conv_direct_dw_dgrad_hostctest: the stream name-overflow cleanup,pad_w < -1, the per-axis padding name, thedgrad/cpl > 1refusal, and the per-axis padding refusal of the six WMMA kernels (including the two stem dgrad kernels). It is listed in thequickandffm-quickcategories ofROCKE_ENGINE_test_categories_external.yaml, so CI runs it.rocke_enginebinding on the path.Test Result
conv_direct_groupedhas 201 configs: the 13 new compiled configs are IDENTICAL, and the 9 new reject configs are BOTH_REJECTED.--checkpasses at every flavor. Every existing hash is reproduced:cpl == 1anddgrad=Falseemit the old IR. The golden diff adds case keys and updates the summary counters.run_diff.py --python-only --check-goldenis GOLDEN OK forllat every flavor and forir_canonical, with 0 unblessed changes and 0 missing. The bless adds 13conv_direct_groupedconfigs (179-190, 197) to each section; no existing hash changes or drops.test_direct_depthwise_dgrad_v2.pyon gfx1250 (before the latest develop merge): 11 passed, 10 subtests (the GPU cases).311cb32338e(feat(rocke): wave32 WMMA stem dgrad for gfx1250 (patch embeddings, small-C stems) #14387, wave32 WMMA stem dgrad), CPU only:--only conv,gfx1250, includingconv_direct_grouped(201 configs),conv_dgrad_patch_wmma(9) andconv_dgrad_smallc_wmma(9);--checkpasses (llvm20 / 22 / 23 / 24); the differential golden is GOLDEN OK forllat every flavor and forir_canonical, with 0 unblessed changes and 0 missing;rocke_conv_direct_dw_dgrad_host;test_direct_depthwise_dgrad_v2.py,test_direct_kernel_cache.py,test_direct_dgrad_wmma.py,test_direct_fwd_wmma.py,test_fwd_small_wmma.py,test_dgrad_stem_wmma.py,test_kernel_label.py: 213 passed, 8 skipped with therocke_enginebinding; 203 passed, 18 skipped without it. The skips need a GPU or the binding;test_direct_depthwise_fwd_cpl.py,test_conv_direct_grouped_backend_parity.py,test_direct_depthwise_col_validate.py,test_conv_dgrad_depthwise_windowed.py: 76 passed, 8 skipped with the binding; 70 passed, 14 skipped without it.ok_casesis 314 / 314 / 342 (llvm20 / 22 / 23). Every case hash equals develop's or this branch's.conv_direct_groupedparity configs and changes noconv_direct_groupedentry of the differential golden (feat(rocke): wave32 WMMA stem dgrad for gfx1250 (patch embeddings, small-C stems) #14387 adds its ownconv_dgrad_patch_wmma/conv_dgrad_smallc_wmmasections), so this PR's configs keep 179-200.PAD); their emitted IR is unchanged.32aed8707aa(feat(rocke): split-K forward implicit-GEMM convolution on gfx1250 #14393 split-K forward conv, feat(rocke): improve conv sweep benchmarks #14379 conv sweep benchmarks), CPU only:ok_casesis 318 / 318 / 347. The golden differs from develop only by this PR's 5 cases per flavor, and every hash equals develop's or this branch's;test_capability_keys.pycaught that its direct capability key left outpad_w; fixed in23b898c8d2cwith a regression test;--only conv,gfx1250(conv_direct_grouped201 configs); golden--checkpasses (llvm20 / 22 / 23 / 24); the differential golden is GOLDEN OK forllandir_canonical;test_capability_keys,test_run_conv_shards,test_module_cache,test_aot_launch_zeroing,test_batched_timing,test_early_stop,test_streamk_sweep_launch) plus the grouped-conv dispatch, split-K forward and this PR's tests: 445 passed, 10 skipped, 1 failed. The failure,test_early_stop.py::test_staged_timing_reports_the_median_of_stalled_samples, fails identically ondevelop.b33ff848a7b(refactor(hip-kernel-provider): split rocKE CMake test registration #14494 split the rocKE CMake test registration intotests/cmake/*.cmake), therocke_conv_direct_dw_dgrad_hostregistration moves verbatim intoplatform/tests/cmake/InstanceTests.cmake;tests/CMakeLists.txtis develop's unchanged. CPU only: byte identity GREEN at llvm20 / 22 / 23 (conv_direct_grouped201 configs), golden--checkpasses (llvm20 / 22 / 23 / 24), the differential golden is GOLDEN OK, native ctest 34/34 (rocke_conv_direct_dw_dgrad_hostpasses),test_cmake_test_registration.py5 passed, and the test counts above are unchanged.64c2954a8e(refactor(rocke): split the representative-IR golden into per-family shards #14679 split the representative-IR golden into per-family shards), this PR's 5 cases per flavor move unchanged into theconv_directandconv_direct_depthwise_tiledshards underplatform/tests/golden/rocke_representative_ir_sha256/; the shards differ from develop's by those additions only. CPU only: golden--checkagainst the shard directory passes (llvm20 / 22 / 23 / 24), byte identity GREEN at llvm20 / 22 / 23, the differential golden is GOLDEN OK, native ctest 34/34, andtest_ir_golden.py/test_rocke_ci_static.py/test_cmake_test_registration.pypass; the test counts above are unchanged.develop. The remaining failures are pre-existing and identical ondevelop:test_conv_abi.py::test_cache_applies_runtime_launch_limits, six cases intest_conv_batch_and_miopen_parse.py,test_conv_dgrad_patch.py::TestPatchIdentity::test_off_keeps_the_historical_hash, andtest_engine_linkage.py::test_installed_pytest_gets_distinct_artifact_environment_variables.Submission Checklist