Skip to content

feat(hipdnn): rocke conv gfx950 dgrad bf16/fp16 engine and ranker - #14822

Merged
bartekxk merged 96 commits into
developfrom
users/barkocot/gfx950-dgrad-aot-catalog-prune-150
Nov 6, 2026
Merged

bartekxk merged 96 commits into
developfrom
users/barkocot/gfx950-dgrad-aot-catalog-prune-150

Conversation

@bartekxk

@bartekxk bartekxk commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

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-packaged
kernels and a trained sort_kernel_catalog ranker — so dgrad dispatch no longer
depends on the Python runtime at inference time.

Technical details

  • rocKE packaging (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.
  • New engine (src/engines/kernel_ingestor_engine/packs/Gfx950ConvDgradGeometry.hpp,
    Gfx950ConvDgradNative.cpp): Gfx950ConvDgradAot, a shape-generic AOT instance
    catalog engine, dispatched through rocKE (8c048ecd49e).
  • Launch plan unification (32f749a6840, 492a77000c0, 52e5425e39a): native
    dgrad 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.
  • Perf:
    • Sub-GEMM tables are now uploaded once at prepare instead of per-launch
      (65b67ad8257).
    • Ingestor descriptor state and catalog views are now shared across containers
      (hashing/caching), cutting duplication and lookup cost for every
      kernel-ingestor engine, not just this one (52da151c47f).
    • Fixed a stale KernelLauncher module-unload bug and i32 kernarg packing
      (9f6efb0a1f2).
  • Codegen / tooling (projects/hipdnn/tools/IngestorGenerator/):
    • enumerate_conv_aot_instances.py / enumerate_conv_dgrad_aot_instances.py and
      make_conv_aot_config.py / make_conv_dgrad_aot_config.py generate and convert
      the gfx950 conv AOT instance catalogs straight from rocKE (0dd5557b3d0,
      f4781c2acb5).
    • Instance lists are tracked as DVC artifacts and treated as a set, not a
      priority order (d670aadba39, 4d3c59c56dd).
  • Catalog pruning: the dgrad AOT catalog was pruned from 640 → 406 instances via
    backward-greedy analysis (median/p90 throughput loss 0%, max <2%), landing as the
    "v3" catalog set (192c882933e, f4f35d8402d); the corresponding UED schema
    revision was bumped twice to match (63e73a62567, 7a5f038e787).
  • Ranker model: a UHD sort_kernel_catalog model for Gfx950ConvDgradAot was
    trained 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).
  • Tests: new unit coverage for the dgrad geometry, matchers, and AOT packs
    (TestGfx950ConvDgradGeometry.cpp, TestGfx950ConvDgradMatchers.cpp,
    TestGfx950ConvDgradAotPacks.cpp), plus a GPU integration test running every
    dgrad AOT instance (IntegrationGpuGfx950ConvDgrad.cpp, ba1bee9117b).

Test plan

  • TestKernelIngestorEngine, TestGenericPlanBuilder, TestWinnerCache,
    TestGlobalKnobDefines (plugin SDK unit tests) — updated/extended for the shared
    descriptor-state and catalog-view refactor.
  • New dgrad-specific unit suites: geometry, matchers, AOT packs, generated test
    vectors/catalog.
  • IntegrationGpuGfx950ConvDgrad — GPU integration test exercising every shipped
    dgrad AOT instance per dtype (BF16/FP16), including poisoned-output and CPU
    reference comparisons, across the full 406-instance catalog.
  • IngestorGenerator Python tests for the new enumerate/make-config/test-vector
    tools (test_enumerate_conv_dgrad_aot_instances.py,
    test_make_conv_dgrad_aot_config.py).
  • rocKE builder test: test_convolution_backward_data_aot_packaging.py.

ASIC Coverage

  • gfx950
  • Command:
    bin/hip_kernel_provider_integration_tests --gtest_filter='*Gfx950ConvDgrad*'
  • Result: 205/205 passed (full binary), of which 171 are the dgrad-specific suite:
    • UnbenchmarkedPlanServesFromTheWholeCatalog — 168 cases (39 graphs x fp16/bf16 x
      per-variant knob pins), each checked against the CPU reference.
    • EveryInstanceMatchesCpuReference — every selectable catalog instance pinned on
      every 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 benchmarking
      path, 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

  • JIRA/ISSUE ID or closing keyword added to description
  • Byte-identity gate re-run if any emission-affecting change touched both
    engines (not applicable here — this is hip-kernel-provider/hipdnn, not the
    Python/C++ rocke lowering engines)
  • ruff check (no --fix) on touched rocke Python
  • Unit tests green (plugin SDK, IngestorGenerator, rocke library)
  • GPU integration test (IntegrationGpuGfx950ConvDgrad) run and passing on
    gfx950
  • Mark PR ready for review (currently draft)

Bartlomiej Kocot and others added 29 commits October 27, 2026 10:11
…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>
@cgmillette
cgmillette enabled auto-merge (squash) November 5, 2026 22:47
…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>
@bartekxk
bartekxk disabled auto-merge November 5, 2026 23:15

@BrianHarrisonAMD BrianHarrisonAMD 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.

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.

@cgmillette

Copy link
Copy Markdown
Contributor

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

Prior item Status
Our 11-02 N3: label order moves gfx950 fwd picks 🟠 OPEN
• author (11-05): out of scope, fwd order untouched (read)
• in scope: this branch's d670aadba3 loosened develop's exact pin (test_grouped_conv_dispatch.py:809), fwd's labels and add --at
• N3c: tiled-first fwd passes 370 of 370 tree tests; develop's pin fails 2 of 5 (ran: checks)
Our 11-03 N12: the batch-chunk GPU test cannot lower the plugin's limit 🟠 OPEN
• author: still open; proposes pinning the implicit-GEMM family plus a host step-count check
• that would answer it (IntegrationGpuGfx950ConvDgrad.cpp:1086)
Our 11-02 N8: body out of date 🟡 OPEN
• unchanged since 11-03; the author edits it on GitHub (read)
• fix: "640 → 406" to 584 → 406; HIPDNN_INGESTOR_CANDIDATE_LIMIT to HIPDNN_INGESTOR_SHORTLIST_LIMIT; drop "catalog views", "(currently draft)"
• its 205/205 predates this push's geometry edits (BrianHarrisonAMD)
Our 11-04 N14: PR numbers in rocKE comments 🟢 FIXED 4ee88c737f
• the 4 rocKE lines now describe the behaviour (read)
• 2 provider-test comments keep 13075 (IntegrationGpuGfx950ConvDgrad.cpp:271, TestGfx950ConvDgradGeometry.cpp:478); Rule 1 covers rocke/ only
Our 11-05 N18 and notice: 15070's copies diverge; fwd-only code here 🟠 OPEN
• half fixed: fwd header, its test and the notice's 17 names gone (c03ea05d52) (read)
• the shared rest, with proposed owners: N18 below
Our 11-05 N19: a second native-namespace rule ignores slug overrides 🟠 OPEN
• new opt-in key native_symbols_from_slug; without it a borrower still gets …unified2_d (ran: probe)
• the key skips develop's - to _ step: slug attn-v2 gives hipkernel.attn-v2 (ran)
• untested, not in the README; no tool main() passes it (make_conv_aot_config.py:762); fix: one rule for own and borrowed names (models.py:653)
Our 11-05 N20: the list tool sweeps under the host's LLVM flavor 🟢 FIXED 4ee88c737f
• unpinned on LLVM 24: exit 1, one line naming ROCKE_LLVM_FLAVOR=llvm22; pinned: both lists match their .dvc md5s (ran)
• its 2 refusal tests failed Windows CI at cca19a2bb8; 2bb9f0e617 pins them: 9 ✓ unpinned here (ran)
• left 🟡: the refusal itself has no test; 4 tests each repeat the pin
Our N1, N2, N6, N9–N11, N13, N15–N17; Copilot ×4; cderb ×3 🟢 FIXED (fu4–fu7)
• N15's doc and N16's skip hint fixed 4ee88c737f: without the lists 2 ✓, 7 skip naming dvc pull (ran)
GarbyGilbertAMD (11-02) ×11 threads + checklist 🟠 OPEN
• 10 of 11 fixed; fwd header now dropped; fwd tools left, in N18 (read)
jakpiase (11-02) ×8 threads 🟠 OPEN
• N12; sticky failed model loads (KernelIngestorEngine.cpp:188); no dX guard tail (IntegrationGpuGfx950ConvDgrad.cpp:771) (read)
• both threads resolved on GitHub, not in code; c03ea05d52's test asserts failed loads stay cached
CongMa13 (11-03, 11-05): reviews; 2 threads 🟠 OPEN
• GenericPlanBuilder.hpp:422: limit now applied per slot (c03ea05d52); BrianHarrisonAMD's thread names the gaps (read)
• convolution_backward_data.py:1364: unchanged, bytearray(Hi) per chunk; no reply (read)
• 11-03 review's items open: N3, N12, fwd tools, jakpiase's
BrianHarrisonAMD (11-06): review; 10 threads 🟠 OPEN
• before merge: slotted limit, the new heuristic test (N21's lines), a gfx950 run at the final head
• agreed: a limited slot record never covers its catalog, so each build re-times; the test never builds a Container (read)
• 7 optional notes, untested blockQ % 4, check_flavor, new key among them; fwd tools non-blocking (N18)
cderb (11-05) approval 🟢 APPROVED 046827ee38
• older head; still counts on develop
• predates c03ea05d52's SDK, generator and header changes
cgmillette (11-05) approval 🟢 APPROVED cca19a2bb8
• older head; still counts on develop
• after it: 2bb9f0e617's 2-line test pin; both superbuilds were red at it
Our overlap notices (11-03, 11-04): findTensor, launchWithParams 🟡 OPEN
• findTensor due now: owner 14242 landed (826bbe8829, in this head); reuse its copy (SdpaGraphMatch.hpp:43) from a pack-generic header, drop Gfx950ConvDgradNative.cpp:94
• only launchWithParams waits: owner 14908 still open; keep IRunnableKernel.hpp:32
Bots / CI 🔴 2 ✗, the PR's; 3 running
• fails: HipDNN Linux Superbuild (+ Summary): N21, red since c03ea05d52 (read: CI logs)
• green: Windows superbuild 274 ✓ + 33 ✓; Linux gfx94X provider shard 104 ✓ (read: CI logs)
• running: Windows gfx110X sanity (queued), then its shards; 2 Linux gfx94X jobs; 85 ✓
• merge: clean; Multi-Arch Summary not posted
Our checks 🟠 Clean merge; N3c, N19 probes red
• merge vs 30056c12cf: clean, 2 behind; develop unmoved at stop (ran)
• build + ctest 49 ✓ (1 skip); byte identity GREEN ×4; goldens pass (ran)
• tests 410 ✓; installed 148 ✓; compile: no new spills (ran)
• N21's lines, reduced: both errors reproduce; both fixes lint clean (ran)
Code quality 🟠 Should-fix
• N18 half fixed: shared helpers now in a dgrad-only home (read)
• N19 open: the new override skips develop's hyphen fold (ran)
• new: N22, an unread profile restates the tool and fails its check (ran)
# Sev file:line Finding
N21 🔴 projects/hipdnn/plugin_sdk/tests/ingestor/uhd/TestUhdKernelHeuristic.cpp:664 c03ea05d52's new test fails clang-tidy in the HipDNN Linux Superbuild
• impact: TestUhdKernelHeuristic.cpp:664:45: error: local copy 'firstContainer' of the variable 'sharedHeuristic' is never modified; consider avoiding the copy [performance-unnecessary-copy-initialization,-warnings-as-errors], same at :665:45; projects/hipdnn/.clang-tidy sets WarningsAsErrors: "*" (read: CI log)
• impact: the build fails at step 939 of 1844, so no Linux superbuild test runs; not a required check, so merged it fails develop's nightly too
• fix: bind both holders by const&, or take BrianHarrisonAMD's two-Container rewrite or removal; a reduced copy lints clean (ran)
N18 🟠 packs/Gfx950ConvDgradGeometry.hpp:34 What both conv engines share now has a dgrad-only home, and 15070 keeps its own copies (update)
• impact: LaunchGeometry, ceilDiv, MagicDivision, magicDivision (:34–:74), DIRECT_KERNARG_NAMES (:1528) equal 15070's (Gfx950ConvFwdGeometry.hpp:47, :928, :205, :211, :352); their rocKE-pairs test left with the fwd test file (read)
• impact: the fwd tools import convolution_forward, which only 15070 has (make_conv_aot_config.py:313, :375); kernel_uuid takes 3 parameters here, 2 there; 15070 is still on develop, not stacked on this branch as the 11-05 decision expects (read)
• owners (proposed: 14822 lands first): 14822 owns the 5 geometry helpers, the dgrad tools' shared imports and 7 pack and test helpers (bufferRangesDoNotOverlap, isDeviceTensor, hasSpatialRankTwo, hasPackedNhwcStrides, candidateCount, dtypeSuffix, gfx950Properties); the fwd tool paths go to 15070
• fix: a neutral packs/Gfx950ConvGeometryCommon.hpp with the magic-division test (as UnifiedAttentionGeometry.hpp serves 2D and 3D), a shared tool module; 15070 stacks here
N22 🟡 IngestorGenerator/configs/gfx950_conv_dgrad_aot.profile.yaml:81 A profile nothing reads restates the tool's knobs and KMD fields
• impact: the README calls it unread (README.md:834); launch_surface.py --check on it exits 1 on its workspace surface; :81 cites an absent dispatch_parity.py (ran)
• fix: delete it and its README row, or keep only launch_surface: and check it as test_launch_surface.py:766 does for dense attention

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 2bb9f0e617 (both hipDNN superbuilds, the Linux provider shard) and the superbuilds at c03ea05d52 and cca19a2bb8; clang-tidy on a reduced copy of the failing lines; the list tool unpinned and pinned; the list tests with and without the lists; the benchmark guard's packing on admitted plans; code quality. Flags whether a closer look is needed; not an approval or rejection.

bartekxk and others added 2 commits November 6, 2026 04:18
…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>
@cgmillette

Copy link
Copy Markdown
Contributor

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

Prior item Status
Our 11-06 N21: new test fails Linux clang-tidy 🟢 FIXED 366d17ac06
• test removed; ABrokenModelIsLoadedAndReportedOnce asserts the same on one instance (read)
• HipDNN Linux Superbuild ✓ at head: tidy build, 194 + 34 ctest ✓ (read: CI log)
Our 11-06 N22: an unread profile restates the tool 🟢 FIXED 366d17ac06
• profile and its README row deleted; nothing references it (read)
Our 11-02 N3: label order moves gfx950 fwd picks 🟠 OPEN
• author (11-05): out of scope; but this branch's d670aadba3 changed fwd's tool and loosened develop's pin (test_grouped_conv_dispatch.py:809)
• 366d17ac06 fixed only the tool's intro (instance_list.py:6–:12): on fwd, labels prints sorted, not file order; add appends last, no --at (ran: exit 1 here, 0 on develop)
• still "every list is a set": 4 docstrings (grouped_convolution.py:62, :979, :1093, :1159), the usage lines (instance_list.py:18), a tool test claiming a sorted fwd file it never writes (test_grouped_conv_dispatch.py:966) (ran)
• N3c: tiled-first fwd passes 370 of 370 tree tests (ran: checks); fix: the tool asks _SET_SEMANTICS_DIRECTIONS (:1210) through a public predicate; --at back for fwd
Our 11-03 N12: the batch-chunk GPU test cannot lower the plugin's limit 🟠 OPEN
• unchanged: no family pin, no launch count (IntegrationGpuGfx950ConvDgrad.cpp:1078) (read)
• author's plan (11-05), a pinAndVerify()-style pin plus a host step-count check, would answer it
Our 11-05 N18 and notice: 15070's copies diverge; fwd-only code here 🟠 OPEN
• fixed: the 17 fwd-only names 15070 owns are gone (read)
• left: what 14822 owns is file-private or dgrad-only, so 15070 cannot drop its copies: N18 below
• author (11-05): 15070's to pick up; but the recorded owner is 14822, landing first
Our 11-05 N19: a second native-namespace rule ignores slug overrides 🟠 OPEN
• 366d17ac06 folds - to _ in the override, tested (test_models.py:115): 0 of 3 override borrowers wrong (ran: probe)
• left: models.py:663 still copies EngineSpec.slug's rule; without the key, 2 of 3 borrowers name an unregistered namespace (ran: probe); README omits the key; :657 says "verbatim"; no tool passes it (read)
• fix: let native_symbols_from name the namespace itself; that retires the slug key
Our 11-02 N8: body out of date 🟡 OPEN
• unchanged; author (11-05) asks for the exact lines (read)
• fix: "pruned from 640 → 406" to "replaces the base's 584 with 406"; HIPDNN_INGESTOR_CANDIDATE_LIMIT to HIPDNN_INGESTOR_SHORTLIST_LIMIT; drop "and catalog views", "(currently draft)"; "a set" holds for dgrad only
• its 205/205 predates the geometry edits (BrianHarrisonAMD)
Our N1, N2, N6, N9–N11, N13–N17, N20; Copilot ×4; cderb ×3 🟢 FIXED (fu4–fu8)
• the delta reopens none (read)
• N20 left 🟡: check_flavor's refusal has no test
GarbyGilbertAMD (11-02) ×11 threads + checklist 🟠 OPEN
• 10 of 11 fixed; left: the fwd tools (N18) (read)
• checklist: ASIC section present; its run predates the geometry edits
jakpiase (11-02) ×8 threads 🟠 OPEN
• left: N12; failed model loads stick, documented, not retried (KernelIngestorEngine.hpp:60); no dX guard tail (IntegrationGpuGfx950ConvDgrad.cpp:771) (read)
• author (11-05) lacks the text: retry an existing artifact that failed, or keep the heuristic per Container; a NaN tail past dX checked after the run
CongMa13 (11-03, 11-05): reviews; 2 threads 🟠 OPEN
• GenericPlanBuilder.hpp:422: scoped, their second option; Environment.md:333 says slotted engines ignore the limit (read)
• convolution_backward_data.py:1364: unchanged, bytearray(extent) per axis; ask: coverage computed arithmetically (read)
• the PR's last 2 open threads, both unanswered; 11-03 items open: N3, N12, fwd tools, jakpiase's
BrianHarrisonAMD (11-06): review; 10 threads 🟠 OPEN
• before-merge: slotted limit dropped as suggested, test removed (366d17ac06); owed: a gfx950 run at the final head, SHA and counts
• 7 of 10 fixed: the blockQ % 4 test catches its mutant (ran); CI guard sees both lists in both superbuilds (read: CI logs)
• author resolved all 10 (11-06), no replies; not done: fwd tools (N18), ValueError and check_flavor tests, fwd labels and add (N3)
cderb (11-05) approval 🟢 APPROVED 046827ee38
• older head; still counts on develop
• predates c03ea05d52's SDK, generator and header changes, and 366d17ac06
cgmillette (11-05) approval 🟢 APPROVED cca19a2bb8
• older head; still counts on develop
• after it: 2bb9f0e617's test pin; 4df60610cb's 3 resolved conflicts; 366d17ac06's SDK limit change
Our overlap notices (11-03, 11-04): findTensor, launchWithParams 🟡 OPEN
• findTensor: as recorded, owner 14242 (landed); Gfx950ConvDgradNative.cpp:94 still a copy (read)
• launchWithParams: owner 14908, still open; IRunnableKernel.hpp:32 stays until it lands
Bots / CI 🟡 Running
• green: both hipDNN superbuilds (Linux 194 + 34, Windows 277 + 33); gfx94X provider shard, 113 entries, 0 ✗; pre-commit, clang-tidy; 92 ✓ (read: CI logs)
• running: a gfx94X tensilelite test; the Windows gfx110X sanity check, its shards after
• merge: clean; blocked: CongMa13's 2 open threads, Multi-Arch Summary pending
Our checks 🟠 Clean merge; N3c, N19 probes red
• merge vs c3fcdb9e6d: clean, 3 behind; develop unmoved at stop (ran)
• build + ctest 51 ✓ / 1 skip; byte identity GREEN ×4; goldens pass, differential 0 changed (ran)
• tests 410 ✓; installed 148 ✓ (3 of 3 changed files); compile: no new spills (ran)
• the new blockQ test against its mutant; fwd add and labels on scratch lists (ran)
Code quality 🟠 Should-fix
• N3 tool half: only the intro fixed; labels still sorts fwd, no --at (ran)
• N18 open: owned helpers file-private or dgrad-only (read)
• N19 half fixed; N22 fixed; blockQ refusal now tested (ran); new: N23
# Sev file:line Finding
N18 🟠 packs/Gfx950ConvDgradGeometry.hpp:32 What 14822 owns stays file-private or dgrad-only, so 15070 cannot drop its copies (update)
• impact: isDeviceTensor, hasPackedNhwcStrides, hasSpatialRankTwo (Gfx950ConvDgradNative.cpp:101, :113, :141), dtypeSuffix, candidateCount (IntegrationGpuGfx950ConvDgrad.cpp:295, :365) and gfx950Properties (TestGfx950ConvDgradMatchers.cpp:152) sit in anonymous namespaces; bufferRangesDoNotOverlap (:154) and the 5 geometry helpers (:34–:74, :1527), which :32 now calls shape- and ABI-free, sit in gfx950_conv_dgrad (read)
• impact: the copies drift: 15070's bufferRangesDoNotOverlap takes int32_t bytes plus an int64_t twin (Gfx950ConvFwdGeometry.hpp:86, :94), this one int64_t; the dgrad tools import the fwd tools (make_conv_dgrad_aot_config.py:51, enumerate_conv_dgrad_aot_instances.py:50), which import convolution_forward, absent here (make_conv_aot_config.py:313) (read)
• fix: a neutral packs/Gfx950ConvGeometryCommon.hpp for the 5 helpers and bufferRangesDoNotOverlap, as UnifiedAttentionGeometry.hpp serves 2D and 3D; the 3 graph predicates in a shared conv pack header; dtypeSuffix, candidateCount in IngestorIntegrationSupport.hpp; an arch parameter on testDeviceProperties() (IngestorPackTestSupport.hpp:174); a shared tool module; 15070 stacks here
N23 🟡 kernel_ingestor_engine/descriptors/README.md:13 4df60610cb's merged table row misnames the gfx942 engine and its pack
• impact: the row says hipkernel:Gfx942AttentionUnified3D, packs/Gfx942AttentionUnified3DNative.cpp; the UED says hipkernel:Gfx942AttentionUnified3d (gfx942_attention_unified3d.ued.json:4), the file is Gfx942AttentionUnified3dNative.cpp; develop's text names neither (read)
• fix: correct the row, or drop the two columns the UEDs and packs/ already own

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 2bb9f0e617 (one commit, and a develop merge with 3 resolved conflicts); merge with develop (build + ctest, byte identity, parity, goldens, the PR's tests source and installed, compile); our saved probes (N3c, N19); CI job logs at 366d17ac06 (both hipDNN superbuilds, the gfx94X provider shard); the new blockQ test against its mutant on a host driver; the fwd tool's add and labels at head and on develop; code quality. Flags whether a closer look is needed; not an approval or rejection.

…arkocot/gfx950-dgrad-aot-catalog-prune-150

# Conflicts:
#	dnn-providers/hip-kernel-provider/rocke/platform/python/rocke/runtime/packing.py
@bartekxk
bartekxk enabled auto-merge (squash) November 6, 2026 14:24
@CongMa13

CongMa13 commented Nov 6, 2026

Copy link
Copy Markdown
Contributor

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.

@cgmillette

Copy link
Copy Markdown
Contributor

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

Prior item Status
Our 11-02 N3: label order moves gfx950 fwd picks 🟠 OPEN
• unchanged since 366d17ac06: fwd labels sorts, add has no --at (read)
• N3c: tiled-first fwd still passes 370 of 370 tree tests (ran: probe)
• fix as in our 11-06 post: a public predicate over _SET_SEMANTICS_DIRECTIONS; --at back for fwd
Our 11-03 N12: the batch-chunk GPU test cannot lower the plugin's limit 🟠 OPEN
• unchanged: no family pin, no launch count (IntegrationGpuGfx950ConvDgrad.cpp:1078) (read)
• the author's 11-05 plan (a pin plus a host step count) would answer it
Our 11-05 N18 and notice: 15070's copies diverge; fwd-only code here 🟠 OPEN
• unchanged; one more shared constant pair: N18 below (read)
Our 11-05 N19: a second native-namespace rule ignores slug overrides 🟠 OPEN
• unchanged: without the slug key, 2 of 3 borrowers name an unregistered namespace (ran: probe)
• fix: native_symbols_from names the namespace itself; that retires the slug key
Our 11-02 N8: body out of date 🟡 OPEN
• unchanged; auto-merge now armed (squash), its stored message this body (read)
• fix: the lines in our 11-06 post, then re-arm so the stored message follows
Our 11-06 N23: merged README row misnames the gfx942 engine and pack 🟡 OPEN
• unchanged (descriptors/README.md:13) (read)
Our N1, N2, N6, N9–N11, N13–N17, N20–N22; Copilot ×4; cderb ×3 🟢 FIXED (fu4–fu9)
• the delta reopens none (read)
• N20 left 🟡: check_flavor's refusal has no test
GarbyGilbertAMD (11-02) ×11 threads + checklist 🟢 APPROVED 73d77b6662
• at head; all 11 threads resolved
• the fwd-tools thread continues as our N18
jakpiase (11-02) ×8 threads 🟠 OPEN
• unchanged: N12; failed model loads stick (KernelIngestorEngine.hpp:60); no dX guard tail (IntegrationGpuGfx950ConvDgrad.cpp:771) (read)
CongMa13 (11-03, 11-05, 11-06): reviews; 2 threads 🟠 OPEN
• GenericPlanBuilder.hpp:422: slotted engines skip the limit, documented (Environment.md:333); no reply (read)
• convolution_backward_data.py:1364: still bytearray(extent) per axis; no reply (read)
• 11-06: asks replies on both, and on our 11-06 posts; both threads block the armed merge
BrianHarrisonAMD (11-06) approval 🟢 APPROVED 366d17ac06
• older head; still counts on develop
• not covered: 73d77b6662's packing.py merge with 14448 (N24)
• their gfx950-run ask: no run posted at a final head (read)
cgmillette (11-05) approval 🟢 APPROVED cca19a2bb8
• older head; still counts on develop
• after it: 2bb9f0e617, 4df60610cb, 366d17ac06; 73d77b6662's packing.py merge
cderb (11-05) approval 🟢 APPROVED 046827ee38
• older head; still counts on develop
• predates c03ea05d52's SDK changes, 366d17ac06, 73d77b6662
Our overlap notices (11-03, 11-04): findTensor, launchWithParams 🟡 OPEN
• findTensor: owner 14242 (landed); Gfx950ConvDgradNative.cpp:94 still a copy (read)
• launchWithParams: owner 14908, still open; the merge plan now lands this PR first
• so, as the notice says, 14908 drops its copy at its rebase; nothing changes here
Bots / CI 🟡 Running
• green: both hipDNN superbuilds (Linux 201 + 32, Windows 284 + 31 ctest); pre-commit, clang-tidy; 91 ✓ (read: CI logs)
• running: gfx94X provider shard, 68 of 119 ✓ so far, rocke_pytest and conv among them (read: log); Windows gfx110X math-libs, shards after; 11 jobs
• merge: blocked: CongMa13's 2 threads, Multi-Arch Summary pending; auto-merge armed
Our checks 🟠 Clean merge; N3c, N19 probes red
• merge vs fa9e0a5578: clean; equal to the checks' merge on every PR path (ran)
• build + ctest 56 ✓ / 1 skip; byte identity GREEN ×4; goldens pass, differential 0 changed (ran)
• tests 410 ✓; installed 148 ✓ (3 of 3 changed files); compile: no new spills (ran)
• tests reaching packing.py on the merge: 1058 ✓, 2 ✗ on develop too; GPU launches pass (ran)
Code quality 🟠 Should-fix
• packing.py resolution: develop's one format table, the PR's wrap in both packers, nothing restated
• the conflict hunk taken from develop, or develop's file, fails test_packing.py (ran)
• new N24: the wrap and 14448's launch contract disagree (ran); N18 grew by one constant pair; N23 open (read)
# Sev file:line Finding
N18 🟠 packs/Gfx950ConvDgradGeometry.hpp:105 What 14822 owns stays file-private or dgrad-only, so 15070 cannot drop its copies (update)
• impact: also DW_DGRAD_WIN_MAX_TENSOR_BYTES, DW_DGRAD_MFMA_CH (:105, :106), mirrors of conv_direct_grouped.py:7802, :7807; 15070 copies both (Gfx950ConvFwdGeometry.hpp:1162; :1157 as DIRECT_WINDOWED_MFMA_CH) (read)
• owner 14822: it lands first, as for N18's other pieces; the rest of N18 unchanged since 11-06
• fix: both into N18's neutral packs/Gfx950ConvGeometryCommon.hpp; 15070 drops its copies
N24 🟡 runtime/packing.py:36 Merged with 14448, the checked launcher refuses i32 values the packer wraps
• impact: from_artifact refuses 2**31 to 2**32 - 1 ("outside I32", contract.py:240); a bytes-built launcher packs them; on develop both refuse (ran: probe)
• fix: one rule for both: wrap where byte counts are made (e.g. grouped_convolution.py:720, :732), packer strict (GarbyGilbertAMD's 11-02 option)

Utility: 🟢 Positive — packing.py resolution keeps both sides; tests catch either side dropped


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 366d17ac06 (a develop merge, one conflict resolved in packing.py); merge with develop and a merge-tree at stop; build + ctest, byte identity, parity, goldens, the PR's tests (source and installed), compile; the tests that reach packing.py on the merge, failures retried on develop; the conflict hunk and develop's file as mutants; our saved probes (N3c, N19, N24 new); CI job logs at 73d77b6662 (both hipDNN superbuilds, the gfx94X provider shard so far); code quality. Flags whether a closer look is needed; not an approval or rejection.

@cgmillette
cgmillette disabled auto-merge November 6, 2026 16:11
@cgmillette

Copy link
Copy Markdown
Contributor

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:

  • our latest review of this exact version found problems to fix first, and they are still open

The open items from our review, each with its fix:

  • N18 (packs/Gfx950ConvDgradGeometry.hpp:105): What 14822 owns stays file-private or dgrad-only, so 15070 cannot drop its copies (update)
    • impact: also DW_DGRAD_WIN_MAX_TENSOR_BYTES, DW_DGRAD_MFMA_CH (:105, :106), mirrors of conv_direct_grouped.py:7802, :7807; 15070

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.

@bartekxk
bartekxk enabled auto-merge (squash) November 6, 2026 16:43
@bartekxk
bartekxk disabled auto-merge November 6, 2026 18:06
@bartekxk
bartekxk enabled auto-merge (squash) November 6, 2026 18:08
@bartekxk
bartekxk merged commit 97abc0b into develop Nov 6, 2026
326 of 328 checks passed
@bartekxk
bartekxk deleted the users/barkocot/gfx950-dgrad-aot-catalog-prune-150 branch November 6, 2026 18:14
AnaghaRaoAMD added a commit that referenced this pull request Nov 6, 2026
…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>
AnaghaRaoAMD added a commit that referenced this pull request Nov 6, 2026
…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>
BradPepersAMD added a commit that referenced this pull request Nov 7, 2026
… 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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants