Repository navigation
feat(hipdnn): rocke conv gfx950 dgrad bf16/fp16 engine and ranker - #14822
Conversation
…s containers A KernelIngestorStateManager owned everything: the schema, the resolved matchers and dispatches, the packs and every kernel definition built from them. One Container per handle meant re-parsing and re-indexing all of it per handle, and every catalog lookup copied a KernelDefinition per candidate -- which a catalog of tens of thousands of AOT instances makes the dominant cost of a plan call. KernelIngestorSharedState now holds the immutable half. A manager binds to one through a shared_ptr and aliases its members, so a second Container over the same descriptor set copies no kernel and rebuilds no index. The manager keeps only the per-handle caches. A cached catalog becomes a CatalogView: pointers into that shared state, published as shared_ptr<const CatalogView> and never mutated after. Ordering one, or adopting a benchmarked record for it, builds a new view and stores that, so a caller holding the older one is never raced. A view costs 8 bytes per kernel instead of a whole definition, which is what bounds the cache. Three lookups that were linear or quadratic per call are now hashed: winner-record coverage and ordering (WinnerCache), the restriction of a calibrated ranking to the pinned candidates, and the knob filter. A pack may also register a KernelPrepareFn under a kernel-scoped matcher's symbol; its payload is computed once when the shared state is built and read from KernelDefinition::prepared, so a matcher no longer decodes the same metadata map on every graph. INGESTOR_CANDIDATE_LIMIT caps the ranked candidate list. It applies before the winner-record lookup, so coverage is judged against the shortlist a benchmark under the same limit measured rather than against the whole catalog. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…r AOT dispatch builders/common/convolution_forward.py gains an AOT path and convolution_backward_data.py is new: both lower one rocKE KernelIdentity into the compiled artefact plus the metadata the hipDNN kernel ingestor matches on, so a packaged kernel is dispatched without Python at run time. The dgrad adapter covers the implicit-GEMM tilde grid and two direct pipelines, depthwise and grouped MFMA, with the MFMA weight transforms packaged as helper kernels: loadable so the pipeline can run, never selectable on their own. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…engines Three kernel-ingestor engines over the rocKE packaging above: hipkernel:Gfx950ConvFwd serves 2D forward cross-correlation from kernels compiled for one geometry each; hipkernel:Gfx950ConvFwdAot and hipkernel:Gfx950ConvDgradAot serve the shape-generic AOT instance catalogs, forward and backward-data. Each ships a native pack that matches the hipDNN graph against the packaged metadata and launches the code object directly. Contract: dense channels-last FP16/BF16, FP32 accumulation, symmetric padding, groups inferred as X channels over W dimension 1. Catalogs hold synthetic verification shapes only. Production catalogs are generated from a private request list and packed from a descriptor root outside the source tree; see docs/gfx950_conv_fwd/README.md. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…talogs
tools/enumerate_conv_{,dgrad_}aot_instances.py turn a curated label list -- one
rocKE KernelIdentity.label() per line -- into the per-dtype instance lists the
packs ship, and tools/make_conv_{,dgrad_}aot_config.py convert those into
generator configs. Nothing is dropped silently: an entry that is not a sweep
identity, or that the converter cannot express, fails the run.
The MFMA dgrad weight transforms are derived rather than listed, by asking rocKE's
own direct_dgrad_weight_transforms() which passes a pipeline runs, so a pipeline
that gains or loses one needs no change here.
codegen gains `native_symbols_from`, letting a test-only engine serve a subset of
a shipped engine's catalog through the shipped engine's registered symbols, and
emits no operation-scoped UMD for a multi-pack engine without discriminators --
one catalog sharded across packs, which is what the AOT catalogs are.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…uct pack jobs uhd_gen: the pipeline server exports HIPDNN_UHD_FEATURE_EVALUATOR as a path in its own checkout, which does not exist inside the training container, so every generate stopped there although the image ships the evaluator on PATH. An evaluator named with --feature-evaluator is still refused when it cannot run; one inherited through the environment is warned about once and the search continues. corpus_gen: conv_bwd_data declares the archetypes the direct dgrad kernels serve, so a corpus covers them. descriptor-packaging: HIPKERNELPROVIDER_PRODUCT_PACK_JOBS sizes the production packer's worker pool, which a catalog of this size needs on a wide host, and the provenance sidecar's cap is taken from its descriptor rather than assumed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
rocKE's dgrad sweep enumerates implicit-GEMM kernels specialized for a filter, stride or dilation, alongside the ones that read all three from their sub-GEMM records at run time. Packaging accepted only the latter: every one of the six extents had to be 0, so 184 of the 640 kernels a current sweep offers could not be shipped at all. An instance may now state them. 0 keeps the old meaning -- runtime, serves every geometry -- so the shipped catalog is unchanged, and a stated extent is a promise the matcher enforces on both sides: _implicit_serves in the adapter and implicitGeometryMatches in the native pack. That gate is not optional. A specialized binary indexes with the extents it was built for, so serving another problem would compute wrong dX rather than fail, which is why the native parser also refuses an instance that states one axis of a pair and not the other. Padding, cpg and kpg stay runtime-only: nothing bakes those into a tilde kernel. The two tests that pinned the old contract now pin the new one, and are built from the sweep rather than the committed catalog, so they state what packaging accepts rather than what today's catalog happens to hold. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The AOT packaging layer was written in October against a rocKE that offered two selectable direct dgrad pipelines and read filter, stride and dilation from the tilde records at run time. rocKE then grew the rest -- the runtime-channel MFMA pipeline (#13529), and the windowed depthwise, fused and 4c pipelines plus baked geometry and the dY-halo/K-decode tuning (#13075) -- while this branch sat unrebased. Rebasing onto develop brought that rocKE in, and 304 of the 648 instances a current sweep offers could no longer be packaged at all. All 648 now are. The pipelines, their knobs and the two weight transforms the runtime-channel one launches are declared; seven implicit-GEMM tuning fields (dy_halo, dy_halo_setprio, dy_halo_kouter_pad, halo_max_wo, patch, tap_outer_k, uniform_k_decode) are carried through to the descriptor, where they were silently dropped before -- two instances differing only in them packaged as one binary. Where this layer mirrored rocKE, it now asks it: the spec factory, the validator, the probe problem and the launch block all come from rocKE itself. The mirrors are what let the layer drift in the first place, and the probe is not cosmetic -- the emitted IR depends on the capability axes, so a probe that does not match them builds a binary the cache offers for shapes it cannot compute. Two knob-set rules changed with the pipelines. A variant's knobs are what it may set, not what it must: the windowed depthwise has a dot2 and an MFMA mode taking different ones. And `grouped` is now a UED knob, not a constant -- a grouped binary also serves groups == 1, so on such a graph it and its ungrouped twin both match and the model has to tell them apart. The catalog is regenerated from the 640-label list: 320 selectable kernels and 4 helpers per dtype, ids stable across the regeneration. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Packaging 648 dgrad variants died on the first windowed depthwise one: hkp_pack: error: variant 'ac4b805f-fbf7-5437-8bb7-d31a0e343c6a' failed to compile for gfx950: HkpPackError: builder call failed (KeyError): 'depthwise_dgrad_win' The previous commit declared the windowed depthwise pipeline, taught the spec factory to ask rocKE's make_direct_spec for it, and wrote 148 of its instances into the catalog -- but the builder behind it was still picked from a hand-written four-entry table in this file, and that table never gained the variant. It was also missing grouped_dgrad_fused and grouped_dgrad_4c, both of which the catalog can carry, so the same crash was waiting for them. Drop the table and call rocKE's own select_direct_kernel_builder, keyed by the sweep algorithm the instance already records. That is the dispatch the direct sweep itself builds through, and it covers all ten algorithms AOT_DGRAD_DIRECT_ALGORITHMS maps, so a pipeline rocKE adds is packageable without another edit here -- the same reason the spec factory stopped mirroring one commit ago. All 648 catalog variants now build; before this, the 148 windowed ones did not. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The dgrad AOT engine's collection_knobs grew from 38 to 61 entries
(dy_halo, patch, ch_per_lane, mfma, w_fold, k_atoms, m_tiles, and
others) without the UED id changing, so the UHD pipeline kept
stamping new collections with the same selector_revision as the old
38-knob dataset and refused to append them ("a dataset holds one
binding, as a model is trained against one"). Bump the UED id/version
so new collections land in a fresh dataset instead of conflicting
with the pre-expansion one.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The previous revision bump changed the engine id and also the UED's "version" to 1.1. That field is the descriptor schema version, not the engine's: the loader refuses a UED of an unsupported schema version, so the engine was silently dropped from the catalog. The new id stays. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…s with Packaged rocKE kernels were linked by whatever COMGR the configure found (an older ROCm's, LLVM 20), while the sweep that chose them links with the newer one: the same configuration compiled to more VGPRs and ran ~1.3x slower. Forward ROCKE_LLVM_FLAVOR (cache variable HIPKERNELPROVIDER_ROCKE_LLVM_FLAVOR) to the packaging step next to the COMGR, and record both in the pack manifest so a stale artifact shows what built it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The dgrad AOT adapter mirrored rocKE's launch rules by hand (grid, launch values, the MFMA pipeline, the sub-GEMM table, when to zero dX) and drifted: it served only four of the eleven direct pipelines the sweep enumerates, ignored the dY halo, tap-outer-K, uniform K decode and patch kernels, and refused every problem over a 2^31-byte tensor. gfx950_conv_dgrad_aot_plan now builds, for an instance and a problem, the whole launch plan -- ordered kernel steps (kernel, ABI, grid, block, buffers and views, scalar values, sub-GEMM table), workspace regions and the dX zero-fill -- from rocKE itself: - implicit GEMM: the identity's own supports_problem, the benchmark's width fold and batch chunks (one image under 2^31 bytes), patch sub-GEMMs, the halo's Wo bound, and dX zero-filled only where the records leave it unwritten; - direct: direct_kernel_sweep.plan_for's steps for every pipeline the sweep enumerates (depthwise stream and window forms, fused, 4c, grouped MFMA, runtime-channel MFMA with its transpose/reorganize helpers), with its launch values. The plan serializes to one int64 sequence with an FNV-1a digest, which the native pack reproduces. Builds refuse an LLVM flavor older than the one the sweep measured with. The tests check the plan against rocKE's own offer and launch values over the shipped catalog, and dX coverage by brute force. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…h plan The native Gfx950ConvDgradAot pack parsed four direct pipelines, ran halo kernels on rows wider than they were compiled for (autotune timed wrong answers), refused patch kernels and large tensors, and had one hand-written launch path per family. Gfx950ConvDgradGeometry.hpp now ports gfx950_conv_dgrad_aot_plan: each instance (implicit GEMM with its halo, patch, tap-outer-K and uniform-K fields; every direct pipeline with its 25 knobs) and problem produce the same Plan as the adapter -- steps, grids, buffers and views, values, sub-GEMM tables, workspace regions, zero-fill -- serialized and digested identically. The kernel matcher admits an instance exactly when a plan exists; the fallback score reads the plan. The dispatch handler executes any plan: one loaded kernel per step (helpers found in the same kpack), a dX memset when the plan asks, each step's sub-GEMM table uploaded to its workspace region, and the arguments laid out by the step's ABI. IRunnableKernel gains launchWithParams for argument lists built at run time. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ter's make_conv_dgrad_aot_test_vectors.py runs the adapter's plan over the shipped catalog and a seeded problem set and writes the golden vectors: each instance's KMD metadata (fields at their KMD default left out), which instances serve each problem with one digest folding their plans, and one plan of each kind in full so a mismatch can be read. The geometry tests compare the native plan with them for every (instance, problem) pair, then check each rule the plan encodes (width fold, batch chunks, patch records, halo bound, zero-fill coverage, MFMA knob fit, workspace layout); the matcher tests drive the kernel matcher, score and helper lookup from the decoded catalog. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The file no longer compiled (rediscoverStateManagersForTesting was renamed rediscoverSharedStatesForTesting), and the saving-handler test listed five of the eight native pack dispatch symbols. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The integration suite now covers every direct pipeline: each graph states, per dtype, how many instances of each variant serve it, and the catalog test pins every one of the 320 selectable instances per dtype on each graph its baked capability admits, poisons dX and compares with the CPU reference. Implicit kernels that bake their filter or stride share every knob with a sibling compiled for another geometry, so the test pins them only on graphs of that geometry. The unbenchmarked tests force each kernel family and direct variant. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The profile listed the knobs, KMD fields and direct variants of the first catalog and launch-surface functions that no longer exist. It now takes the knobs and fields from make_conv_dgrad_aot_config, names all eleven direct variants, and maps each launch-surface item to the plan functions on both sides. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Every implicit-GEMM launch copied its record table from pageable host memory into the caller's workspace before the kernel: a synchronous staging copy on the timed stream, ~3.4 us per call, which hipDNN timing and autotune both counted and the rocKE sweep (one upload before timing) did not. A table depends on the instance and the problem only, so the prepared plan now owns a device copy of its SUB_GEMM region, uploaded once in prepare and freed with the plan. Implicit GEMM asks the caller for no workspace; the MFMA pipelines' regions are unchanged. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…g model for gfx950 Generated by the UHD pipeline (model uhd_gfx950-hipkernel_Gfx950ConvDgradAot_sort_kernel_catalog_5efbfa95). - uhd id: a50c7880-e4a5-436b-850b-5123f1bd4a4e (bound in dnn-providers/hip-kernel-provider/src/engines/kernel_ingestor_engine/descriptors/rocKE/gfx950_conv_dgrad_aot's UED under sort_kernel_catalog.default) - metric: tflops - trained against: the descriptor set at the SHA below - hipDNN built at: 65b67ad - trained on: 4997 graph(s) measured on gfx950-mi355x (8 GPU(s) on 6 node(s)) under ROCm 7.14.0, HIP 7.14.60850-0000000, 2026-10-28 - held-out validation: passed, 200 graph(s), the evaluation slices of corpus_gfx950-hipkernel_Gfx950ConvDgradAot_6778e1c1 - held-out mean top-1 regret: 0.0357 (shipped ranker: n/a)
…catalog The 234-instance catalog cut (640->406 labels) doesn't itself change the engine's shape applicability, so it doesn't bump the UED id automatically -- but it does change what the sort_kernel_catalog ranker is choosing among. Collecting under the unchanged revision would land new (406-instance) measurements in the same dataset as the existing 182,462-row collection measured against the full 640-instance catalog, mixing winner labels from two different catalogs under one selector_revision. Bump the UED id (not "version", which is the descriptor schema version -- see 4d3821a) so a fresh collection lands in its own dataset. Move the currently shipped heuristic to the new revision directory unchanged; the shipped model itself is untouched, just relocated to stay reachable under the new id. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…g to 406 instances Backward-greedy analysis of dgrad_autotune_instance_times.csv (1098 real workload shapes x 598 original instances) showed 128 of 278 dtype-shared templates can be dropped with median/p90 per-case loss = 0%, max < 2% -- 11 of those (halo/tap-outer-K geometries whose hwo/hkp/hprio value had no other remaining representative in any benchmarked shape) were restored unconditionally as a safety margin against unobserved K/C/G ranges, for a net 234 dropped instances (117 templates x fp16+bf16) out of 640. - rocke/instances_dgrad.txt: 640 -> 406 labels (the DSL manifest). - Mirrored IngestorGenerator/configs/gfx950_conv_dgrad_aot.labels.txt (same cut, header comment updated) and its regenerated per-dtype instance lists (141 implicit + 62 direct + 4 helper = 207/dtype). - test_convolution_backward_data_aot_packaging.py: catalog size assertion (>600 -> >400). - test_enumerate_conv_dgrad_aot_instances.py: kernel-per-dtype count (320 -> 203; implicit_gemm 247->141, direct_depthwise_dgrad 12->9, direct_depthwise_dgrad_win 37->31, direct_grouped_dgrad_fused 18->16). Full methodology and safety-exception list: rocke/docs/ dgrad-aot-catalog-prune-150/generate_prune_list.py and its output JSON. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…g model for gfx950 Generated by the UHD pipeline (model uhd_gfx950-hipkernel_Gfx950ConvDgradAot_sort_kernel_catalog_1a9642e7). - uhd id: 81f666a1-6204-40f1-8e6d-ccad01bdbcae (bound in dnn-providers/hip-kernel-provider/src/engines/kernel_ingestor_engine/descriptors/rocKE/gfx950_conv_dgrad_aot's UED under sort_kernel_catalog.default) - metric: tflops - trained against: the descriptor set at the SHA below - hipDNN built at: 192c882 - trained on: 6195 graph(s) measured on gfx950-mi355x (10 GPU(s)) under ROCm 7.14.0, HIP 7.14.60850-0000000, 2026-10-29 (25567 repeated row(s) set aside for better measurements) - held-out validation: passed, 200 graph(s), the evaluation slices of corpus_gfx950-hipkernel_Gfx950ConvDgradAot_6778e1c1, corpus_gfx950-hipkernel_Gfx950ConvDgradAot_bba263db - held-out mean top-1 regret: 0.0245 (shipped ranker: 0.0295)
The per-dtype instance lists (gfx950_conv_{fwd,dgrad}_aot_{fp16,bf16}
.instances.json) are generated output, now regenerated from rocKE's own
registered instance lists (read_rocke_catalog) instead of the removed
labels.txt mirror. DVC-add them (pointer committed, data pushed
separately with explicit confirmation) instead of committing the raw
JSON, consistent with how other generated/large artifacts in this repo
are tracked.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
InstanceList's default pick used to be "first in the file", so the file's insertion order silently acted as an unwritten priority table. Sort by the instance's own label (_instance_sort_key) on write and on read instead: the file is canonical regardless of insertion order, and the default pick is now a deterministic function of the catalog's content, not its history. Drop instance_list.py's `add --at N` (no longer meaningful once every write re-sorts). Update test_grouped_conv_dispatch.py for set semantics (registry-is-exactly-the-lists by set equality, not file order; default pick reasoned about by label order). Also fixes a real bug in grouped_convolution.py's _signature(), found by the label-sort change exposing it on direct_grouped_dgrad_4c/_fused (DIRECT_DGRAD_FPROP_SINGLE): these are forward-builder kernels over a transposed problem, like the `spec.helpers` case already handled, but lacked `spec.helpers` themselves and so got dgrad-style kernarg names instead of fwd-style. Fixed in both _signature() and launch_plan_for() (the two must agree). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Replace the registered gfx950_dgrad.json instances with the 454 labels in docs/dgrad_instances_v3.txt -- a deliberate content swap, independent of the paused 150-template-prune analysis in docs/dgrad-aot-catalog-prune-150-plan.md (which stays untouched for a possible later resumption once UHD is back). gfx950_fwd.json is only reformatted (now-canonical sorted-by-label order, written by the previous commit's format_instance_list()); its instance set is unchanged (1466 = 1466 labels before/after). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ht from rocKE
read_rocke_catalog(direction) replaces the hand-maintained labels.txt mirror:
it loads dispatch.grouped_convolution.load_instance_list() on rocKE's own
gfx950_{fwd,dgrad}.json directly, so rocKE is the single source of truth for
"what instances exist" and the two trees can no longer drift out of sync
(the failure mode that stalled the prune-150 catalog cut -- the mirror
needed a separate, blocked manual edit).
read_excludes(path) replaces the labels file's role for known-bad instances
(label -> reason, JSON); CATALOG_LABELS/read_labels() stay as a still-tested,
now-unused general label-file parser. Regenerated
gfx950_conv_dgrad_aot_{fp16,bf16}.instances.json (231/dtype: 164 implicit +
63 direct + 4 helper) from the v3 catalog -- the committed .dvc pointers
already matched this content byte-for-byte (regenerated once already in this
tree's working state before being DVC-tracked), so there is nothing new to
push.
Tests updated to stop pinning instance counts rocKE's catalog now owns
(test_the_catalog_lists_the_same_kernels_for_both_dtypes replaces the
203-per-dtype/family-count assertions) and to read the catalog instead of
a fixture labels.txt.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The v3 catalog content swap (454 labels replacing the 406-instance prune-150 set) doesn't itself change the engine's shape applicability, so it doesn't bump the UED id automatically -- but it does change what the sort_kernel_catalog ranker chooses among, same reasoning as the prune-150 bump (63e73a6): collecting under the unchanged revision would land new (v3-catalog) measurements in the same dataset as the existing collections measured against the prune-150 and original 640-instance catalogs, mixing winner labels from three different catalogs under one selector_revision. Bump the UED id only (not "version", the descriptor schema version -- see 4d3821a); the heuristics/ shipped-model directory move already landed in the prior commit that touched this tree's catalog mechanism. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…g model for gfx950 Generated by the UHD pipeline (model uhd_gfx950-hipkernel_Gfx950ConvDgradAot_sort_kernel_catalog_62e8f9da). - uhd id: 9ab01cdd-c99c-4c22-87ea-9486bc09d17c (bound in dnn-providers/hip-kernel-provider/src/engines/kernel_ingestor_engine/descriptors/rocKE/gfx950_conv_dgrad_aot's UED under sort_kernel_catalog.default) - metric: tflops - trained against: the descriptor set at the SHA below - hipDNN built at: 7a5f038 - trained on: 6590 graph(s) measured on gfx950-mi355x (38 GPU(s) on 8 node(s)) under ROCm 7.14.0, HIP 7.14.60850-0000000, 2026-10-31 - held-out validation: passed, 200 graph(s), the evaluation slices of corpus_gfx950-hipkernel_Gfx950ConvDgradAot_1d84c132, corpus_gfx950-hipkernel_Gfx950ConvDgradAot_ae501dbc - held-out mean top-1 regret: 0.0366 (shipped ranker: 0.0730)
…acking The grouped-conv sweep benchmark builds a fresh, uncached KernelLauncher per instance; nothing called hipModuleUnload on the previous ones, so a long sweep (hundreds of instances) leaked HIP modules until the device ran out of memory. Add KernelLauncher.unload() and call it once each sweep step is timed/verified. Also fix pack_args/compile_packer to reinterpret an i32 kernarg as its two's-complement bit pattern when the value does not fit in a signed i32 — needed for buffer-descriptor NUM_RECORDS fields (e.g. A_bytes/D_bytes) on large-tensor dgrad instances, which the sweep's exhaustive catalog search started exercising. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ests test_main_refuses_a_listed_helper and test_main_refuses_a_forward_kernel feed main() a single fake identity without pinning the environment's LLVM flavor to it, unlike test_committed_instance_lists_are_what_the_tool_enumerates. On a host whose detected flavor differs from the identity's own (e.g. CI's llvm24 vs. the committed catalog's llvm22), check_flavor() now fires first and masks the "derived, not registered" / "not a gfx950 dgrad sweep identity" message these tests assert on. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
BrianHarrisonAMD
left a comment
There was a problem hiding this comment.
Thanks for addressing the earlier feedback. Three items before merge: the slotted shortlist limit, the new heuristic test, and a gfx950 run on the final head. The forward-tooling note and the comments marked optional are non-blocking.
Since CI has no gfx950 runner, please run hip_kernel_provider_integration_tests --gtest_filter='*Gfx950ConvDgrad*' on gfx950 at the final head and post the SHA and pass counts. The 205/205 result predates the latest geometry changes.
|
Automated review: Model - qwen3.6:35b-a3b-coding-mtp-q4_K_M, effort: max PR #14822 — rocke conv gfx950 dgrad bf16/fp16 engine and ranker (bartekxk, AICK-2562) — 🔴 Follow-up: new test breaks Linux tidy
Utility: 🟡 Mixed — N14, N16, N20 fixed as advised; a new test breaks Linux CI. 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 and a merge-tree at stop; build + ctest, byte identity, goldens, the PR's tests (source and installed), compile; our saved probes (N3c; N19 saved this round); CI job logs at |
…arkocot/gfx950-dgrad-aot-catalog-prune-150 # Conflicts: # dnn-providers/hip-kernel-provider/src/CMakeLists.txt # dnn-providers/hip-kernel-provider/src/engines/kernel_ingestor_engine/IngestorKernelCode.hpp # dnn-providers/hip-kernel-provider/src/engines/kernel_ingestor_engine/descriptors/README.md
…flaky shared-heuristic test, and other small cleanups GenericPlanBuilder's slotCandidates path applied shortlistLimit without ever being exercised by a slotted-engine test and without accounting for the narrowed shortlist in setSlotProgramBenchmark's re-benchmark check; drop it and note in Environment.md that slotted engines ignore the limit. Remove ABrokenModelsFailureIsSharedAcrossEveryHolderOfTheHeuristic, which only copied one shared_ptr under two names rather than exercising two Containers, and which also failed clang-tidy's unnecessary-copy check. Normalize hyphens in native_symbols_from_slug the same way slug_override already is. Add a block_q % 4 refusal case to the FOUR_C direct pipeline test. Reword two Gfx950ConvDgradGeometry comments to describe the helpers instead of their removed-engine history. Delete the unread gfx950_conv_dgrad_aot.profile.yaml and its README row. Avoid CRLF when make_conv_dgrad_aot_config.py writes on Windows. Correct the rocKE toolchain README: only ROCKE_COMGR_LIB reaches the ctest entries, not ROCKE_LLVM_FLAVOR. Make the superbuild CI's dvc-pull guard check the bf16 and fp16 instance lists separately so a partial pull is not mistaken for a full one. Clarify instance_list.py's docstring: only dgrad's list is sorted on canonical write, fwd keeps its hand-tuned priority order. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
Automated review: Model - qwen3.6:35b-a3b-coding-mtp-q4_K_M, effort: max PR #14822 — rocke conv gfx950 dgrad bf16/fp16 engine and ranker (bartekxk, AICK-2562) — 🟠 Follow-up: Linux tidy fixed; four items open
Utility: 🟢 Positive — Linux tidy fixed; slotted limit dropped cleanly; blockQ refusal now tested 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: delta since |
…arkocot/gfx950-dgrad-aot-catalog-prune-150 # Conflicts: # dnn-providers/hip-kernel-provider/rocke/platform/python/rocke/runtime/packing.py
|
I reviewed this PR again. The following review threads are still unresolved, or comments have no author reply:
For reassessment, the PR author should reply to top-level feedback or state that thread feedback is addressed. Before approval, top-level comments need explicit resolution from their author or that author's approval of the PR. |
|
Automated review: Model - qwen3.6:35b-a3b-coding-mtp-q4_K_M, effort: max PR #14822 — rocke conv gfx950 dgrad bf16/fp16 engine and ranker (bartekxk, AICK-2562) — 🟠 Follow-up: merge resolved; four items open
Utility: 🟢 Positive — 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: delta since |
|
Automated merge-queue status (rocKE merge monitor) Hi @bartekxk, 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 (#14822 (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. |
…2-dense-aot Conflicts with #14822 (gfx950 conv dgrad AOT engine), resolved: - IRunnableKernel.hpp: both added launchWithParams with one signature; keep develop's. - test_packs.cpp.j2: develop's constexpr-array inventory replaces this branch's long-name fence; this branch's line-wrap rules stay. The four attention census tests develop did not regenerate are regenerated (same pack and kernel names). - config_loader.py, test_config_loader.py, test_slots.py: develop's split (unslotted knobs int or string, slot knobs int) replaces this branch's single check, and this branch's slot string-knob test goes. - integration_tests/CMakeLists.txt: this branch's knob-suite table plus develop's dgrad test block. - kernel_ingestor_engine/CMakeLists.txt, descriptors/README.md, IngestorIntegrationSupport.hpp: both sides kept; the README table gains Gfx942AttentionDense and spells Gfx942AttentionUnified3d as the engine and pack are named. - unslotted_render_golden.json: recomputed from the merged generator. Co-Authored-By: Claude <noreply@anthropic.com>
…ention engines #14822's Gfx950ConvDgradAot census block repeated the nine generated Packs cases that src/tests/CMakeLists.txt keeps in one list, and gated on its own per-engine wrapper over hkp_product_ships_engine_for_arch. It now uses the shared list and the predicate directly, as the attention engines do, and the wrapper goes. Co-Authored-By: Claude <noreply@anthropic.com>
… the newer fields The gfx950 rocKE conv dgrad engine (#14822) gates tensor alignment (multiples of 16 bytes), declines ragged, pass-by-value and override-shape graphs, but its UED claimed graph schema 1.0.0. Both the provider's schema guard and the SDK plan builder's understandsGraph therefore declined every graph declaring 32- or 64-byte alignment (floor 1.3.0), which the matcher serves. Declare 1.3.0 at the source (make_conv_dgrad_aot_config.py) and in the shipped UED, update the generated census expectation, and add the engine to TestContainer's opt-in list. Tests: the graph matcher accepts 32/64-byte alignment; on gfx950 an aligned dgrad graph built through the frontend gets a plan on this engine and matches the CPU reference. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Motivation
Ship an ahead-of-time (AOT) hipDNN kernel-ingestor engine for grouped convolution
backward-data (dgrad) on
gfx950, in BF16 and FP16, backed by rocKE-packagedkernels and a trained
sort_kernel_catalogranker — so dgrad dispatch no longerdepends on the Python runtime at inference time.
Technical details
library/builders/common/convolution_backward_data.py):packages every dgrad pipeline rocKE's sweep enumerates, including a "tilde"
kernel compiled for one fixed geometry, for AOT dispatch without a Python
runtime.
src/engines/kernel_ingestor_engine/packs/Gfx950ConvDgradGeometry.hpp,Gfx950ConvDgradNative.cpp):Gfx950ConvDgradAot, a shape-generic AOT instancecatalog engine, dispatched through rocKE (
8c048ecd49e).32f749a6840,492a77000c0,52e5425e39a): nativedgrad AOT launch plans are now derived directly from rocKE's own sweep instead of
hand-mirrored launch rules, and pinned by test to match the adapter's plan.
prepareinstead of per-launch(
65b67ad8257).(hashing/caching), cutting duplication and lookup cost for every
kernel-ingestor engine, not just this one (
52da151c47f).KernelLaunchermodule-unload bug and i32 kernarg packing(
9f6efb0a1f2).projects/hipdnn/tools/IngestorGenerator/):enumerate_conv_aot_instances.py/enumerate_conv_dgrad_aot_instances.pyandmake_conv_aot_config.py/make_conv_dgrad_aot_config.pygenerate and convertthe gfx950 conv AOT instance catalogs straight from rocKE (
0dd5557b3d0,f4781c2acb5).priority order (
d670aadba39,4d3c59c56dd).backward-greedy analysis (median/p90 throughput loss 0%, max <2%), landing as the
"v3" catalog set (
192c882933e,f4f35d8402d); the corresponding UED schemarevision was bumped twice to match (
63e73a62567,7a5f038e787).sort_kernel_catalogmodel forGfx950ConvDgradAotwastrained and retrained across the catalog/knob iterations, landing at ~0.0366
held-out validation regret on 6590 graphs; KDPs and the heuristic model are kept
in DVC under
descriptors/rocKE/gfx950_conv_dgrad_aot/(f520242f383,9662adc7545,2a2ea2dafe5,ec41b3e423b,273658d6a3b).(
TestGfx950ConvDgradGeometry.cpp,TestGfx950ConvDgradMatchers.cpp,TestGfx950ConvDgradAotPacks.cpp), plus a GPU integration test running everydgrad AOT instance (
IntegrationGpuGfx950ConvDgrad.cpp,ba1bee9117b).Test plan
TestKernelIngestorEngine,TestGenericPlanBuilder,TestWinnerCache,TestGlobalKnobDefines(plugin SDK unit tests) — updated/extended for the shareddescriptor-state and catalog-view refactor.
vectors/catalog.
IntegrationGpuGfx950ConvDgrad— GPU integration test exercising every shippeddgrad AOT instance per dtype (BF16/FP16), including poisoned-output and CPU
reference comparisons, across the full 406-instance catalog.
IngestorGeneratorPython tests for the new enumerate/make-config/test-vectortools (
test_enumerate_conv_dgrad_aot_instances.py,test_make_conv_dgrad_aot_config.py).test_convolution_backward_data_aot_packaging.py.ASIC Coverage
bin/hip_kernel_provider_integration_tests --gtest_filter='*Gfx950ConvDgrad*'UnbenchmarkedPlanServesFromTheWholeCatalog— 168 cases (39 graphs x fp16/bf16 xper-variant knob pins), each checked against the CPU reference.
EveryInstanceMatchesCpuReference— every selectable catalog instance pinned onevery graph it could serve: 203/203 instances per dtype ran (fp16 and bf16),
2066 pinned executions per dtype checked against the CPU reference.
CappedBenchmarkMatchesCpuReference— HIPDNN_INGESTOR_CANDIDATE_LIMIT benchmarkingpath, same coverage.
Deliverable set correction
The base registered 584 dgrad instances (292 per dtype). This PR replaces that set with
406 (203 per dtype: 141 implicit-GEMM + 62 direct), not a 640 -> 406 prune as an earlier
draft of this description said. Compared by normalized label, only 96 of the 406 are in
the base list (48 per dtype); 488 base instances are dropped and 310 are new. See
IngestorGenerator/configs/gfx950_conv_dgrad_aot_{fp16,bf16}.instances.json and
tools/make_conv_dgrad_aot_config.py for how the 406 are derived and kept 1:1 with the
registered dispatcher list (gfx950_dgrad.json).
JIRA ID: AICK-2562
Submission checklist
engines (not applicable here — this is hip-kernel-provider/hipdnn, not the
Python/C++ rocke lowering engines)
ruff check(no--fix) on touchedrockePythonIntegrationGpuGfx950ConvDgrad) run and passing ongfx950