Skip to content

feat(hipdnn,hip-kernel-provider): hip and hsaco multi-launch kernels, launch-set checks and an end-to-end test - #14215

Merged
GarbyGilbertAMD merged 45 commits into
developfrom
users/ggilbert/ALMIOPEN-2973/follow-ups
Oct 30, 2026
Merged

GarbyGilbertAMD merged 45 commits into
developfrom
users/ggilbert/ALMIOPEN-2973/follow-ups

Conversation

@GarbyGilbertAMD

@GarbyGilbertAMD GarbyGilbertAMD commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Follow-ups to #14158 (multi-launch sources kernel descriptors). A sources map may now author hip and hsaco entries as well as rocke, so a HIP or prebuilt-code-object multi-stage kernel can go through the packer. The packer refuses a pack in which kernels served by one dispatch handler name different launch sets. A device test runs a packer-built multi-launch kernel end to end through an engine, with a workspace hand-off between its launches. Saving an execution plan of a multi-launch kernel is refused for having several launches, rather than as an embedded_source kernel. The remaining review items from #14158 are closed with tests, tooling fixes and docs.

JIRA ID : ALMIOPEN-2973

Risk Assessment

Risk 3 of 5. The change extends the packer (hkp_pack) and IngestorGenerator with a new authoring path, adds a pack-time refusal, and adds three inline helpers to the plugin SDK ingestor headers. Single-launch descriptors and rocke sources pack and load as before; the state manager's launch-set and adaptability rules are unchanged and only move into shared helpers. The new packer refusal can fail a pack that used to succeed, but such a pack already had kernels dropped at load. Execution-plan saving refuses a multi-launch kernel with the same status as before and a corrected message, and the serialization behavior note is unchanged for every engine. Consumer-agreement evidence stays rocke-only, so hip/hsaco sources kernels are treated like their single-launch counterparts (a declaration with metadata_fields over them is refused). The packer, the state manager and the validator also overlap with the open kernel-slots implementation (#13972), so whichever lands second will need a rebase.

ASIC Coverage

Host-side packaging, loading, plan-save checks and tooling, plus a test-only fixture. No kernel, support surface, selection rule or default changes. Passing PR CI is sufficient. The device tests also ran and passed on gfx90a.

Testing Summary

  • End to end on device: TestMultiLaunchEndToEnd loads a UKD 1.1 hip sources kernel packed by hkp_pack (two launches on one translation unit, one code object, two symbols), selects it through an engine with a test-only dispatch handler, and executes it. The first launch writes the workspace and the second reads it. The asserted output is reachable only if both launches run, in order, over one workspace. Host-only cases check that a handler declaring fewer launches drops the kernel and logs both launch sets.

  • Plan saving: a plan over a multi-launch kernel whose launches are all kpack is refused for having several launches, and the message does not call it an embedded_source kernel.

  • Packer: hip and hsaco sources (compile and read once per shared source, per-launch symbol and signature, provenance, desk check, refusals for role, a missing hsaco arch, mixed kinds and metadata_fields). Also the pack-time launch-set check, including two KDPs that share one UDD and two UDDs that name one dispatch symbol, and kills for previously surviving mutants: compile grouping by library and toc key, the desk-check reader per launch, and launch-order insensitivity.

  • Probes: hip and hsaco launches checked by archive membership, digest, symbol and signature without rocke evidence; rocke evidence still required. Also per-launch sweep keys and group keys, and launch-order insensitivity.

  • IngestorGenerator: the generated multi-launch launchNames() stub is now compiled, its census arm parsed, and its launch set checked against the config. launches on hip and hsaco kernel sources is accepted. verify_variant_sets keys hip and hsaco launches by their own identity and ignores sources key order.

  • Validator: a committed fixture whose kernels name different launch sets fails validation and names both sets.

  • Mixed-version check (manual): a validator built from develop just before feat(hipdnn): support multi-launch rocKE kernels in kernel descriptors #14158 skips UKD 1.1 kernels with a version warning instead of misloading them. A pack holding only 1.1 kernels is dropped; in a mixed pack its 1.0 kernel is kept.

  • Mutation checks: every new test was run against a targeted source mutant and failed. Examples: state manager keeping every kernel, plan passing no workspace, every launch given the first launch's symbol, signatures keyed per code object instead of per symbol, plan capture reading the kernel's source instead of its launches.

  • Review follow-ups from feat(hipdnn): support multi-launch rocKE kernels in kernel descriptors #14158. The new tests cover:

    • each launch's symbol, toc key and sha256 changing the engine-selector revision;
    • a device-free check that each launch's signature is checked against its own expected signature before its archive is opened;
    • the desk check catching a toc key shared between a single-launch kernel and one launch of a multi-launch kernel;
    • an accessor that raises AttributeError failing the observation instead of counting as unreported;
    • empty launch target/role overrides being refused;
    • a nesting case that differs only in a launch name.

    Each was run against a targeted source mutant and failed.

Testing Checklist

  • hipDNN superbuild, Linux, kernel ingestor, tooling tests and rocKE ON, GPU hidden - ctest --test-dir build --output-on-failure --no-tests=error - Status: Passed (236 registered; the 3 skips are 2 sample tests and the rocKE arch-domain reproduction test, none of them changed here)
  • Multi-launch and plan-save device tests - hip_kernel_provider_tests --gtest_filter='TestMultiLaunch*:TestLaunchKernelDefinition*:TestIngestorPlanCapture*:TestRestoredIngestorPlan*:TestIngestorPlanRoundTrip*' - Devices: gfx90a - Status: Passed (26/26)
  • IngestorGenerator suite - ctest -R hipdnn_ingestor_generator_pytest (strict skips) - Status: Passed (1545 passed, 0 skipped)
  • Packer, probe and validator suites - ctest -R 'hkp|probe|validate_descriptors' - Status: Passed
  • pre-commit - GitHub check - Status: Passed
  • PR CI - GitHub PR checks - Status: Pending

Technical Changes

  • hkp_pack: authored sources entries may be hip (source, entry, build) or hsaco (file, symbol), one kind per map. Entries sharing a translation unit and build, or an hsaco file, share one code object and toc key; each launch keeps its own symbol and signature. Provenance records each launch's authored identity under provenance.sources. role, consumer agreement and check_claims stay rocke-only; embedded_source and authored kpack entries stay refused.
  • Pack-time launch-set check: within an arch shard, every kernel served by one dispatch symbol (the dispatch_symbol of its KDP's UDD, which is how the loader resolves the handler) must name one launch set (a single-launch kernel's set is empty); otherwise the pack fails naming the symbol, each KDP and each kernel's set. KDPs that share a UDD, or name one symbol from two UDDs, are held to one set. The check sees one packaging root, so two roots that register the same symbol are not compared. The probe end-to-end fixture's fused multi-launch KDP gets a UDD of its own, since its single-launch siblings share the original one.
  • Plugin SDK: Descriptors.hpp holds the readers of a kernel's launches. launchNamesOf() builds a kernel's launch-name set, for the state manager and hipdnn_validate_descriptors. A multi-launch kernel leaves source default, which reads as an embedded_source kernel, so singleLaunchSource() returns a single-launch kernel's one source and null for a multi-launch kernel, and allLaunchSources() tests every launch. The state manager's adaptability check, buildForSourceKind, plan capture and the serialization behavior note read through them; the engine-selector digest still hashes both fields as before.
  • Execution-plan saving: the saved payload holds one kernel image, so capture refuses a multi-launch kernel for having several launches instead of reading its default source. Saving these plans is tracked in ALMIOPEN-3031.
  • Probes: Kind.launch_evidence decides whether a kind's launches carry rocke effective-spec evidence; hip and hsaco launches get the structural per-launch checks.
  • IngestorGenerator: launches on hip and hsaco kernel sources, with per-kind override keys; verify_variant_sets identities for hip and hsaco launches.
  • Tests and fixtures: new multi_launch descriptor set, packed beside the unit and integration roots so no Container loads it; validator fixture multi_launch_mismatch; the _restamp test helper moved to pack_helpers.py.
  • Docs: RFC 0017 §15.4/§15.5 corrected and the accepted sources kinds stated; RFC 0009, the provider README and the plugin development guide state that a multi-launch kernel's plan cannot be saved yet; a worked multi-launch handler in the ingestor-engine native-pack.md guide; packaging, generator and fixture READMEs updated.
  • Review follow-ups (feat(hipdnn): support multi-launch rocKE kernels in kernel descriptors #14158):
    • The desk check's toc-key uniqueness now counts two kernels as one when any launch of one shares a toc key with any launch of the other.
    • Unknown sources kinds share one refusal message.
    • Empty launch target/role overrides are refused.
    • launchKernelDefinition no longer copies the sources map only to discard it.
    • The RFC 0017 §15.1 example is marked abridged, and the "fill every Launch" loader check is described as arriving with launches[].

Related: #14158 (multi-launch kernel descriptors), #13315 (saving and loading ingestor execution plans), #13839 (RFC 0021, kernel slots), #13972 (kernel-slots implementation), #13897 (RDNA SDPA catalog, a future sources user).

…vice

A kernel descriptor carrying a sources map had been exercised only in pieces: the loader
and state manager on hand-built definitions, and launchKernelDefinition over one module.
Nothing loaded such a kernel from a tree, selected it through an engine and ran its
launches with a workspace between them.

A new test descriptor set, multi_launch, packs one HIP translation unit exporting two
kernels. It is staged beside the unit and integration roots rather than inside them, so no
Container loads it and the engine lists of both test binaries are unchanged. At run time
the test rewrites the packed descriptor into a UKD 1.1 sources kernel with a produce and a
consume launch, loads that tree on its own and registers a test-only graph match and
dispatch handler. On a device the engine is selected, planned and executed: produce writes
the workspace, consume reads it, and the exact output is reachable only when both launches
run, in order, over the same workspace. A host-only case checks that a handler declaring
fewer launches drops the kernel at load and logs both launch sets.

ALMIOPEN-2973
The state manager and the descriptor validator each built the set of a kernel's launch
names from its sources map with their own loop, and the two must agree for the
validator's stub handler to model the runtime. launchNamesOf() in the plugin SDK's
descriptor header now computes the set once, empty for a single-launch kernel, and both
call it.

ALMIOPEN-2973
… launch sets

A pack's native dispatch handler declares one set of launch names, and the state manager
drops a kernel whose set differs, so a variant with another launch set belongs in its own
pack. The packer accepted such a pack with exit 0 and left the mistake to the validator
and the runtime. hkp_pack now checks each KDP of an arch shard before packing and fails
naming the KDP and every kernel's launch set; a single-launch kernel beside a
multi-launch one fails the same way, and the order of sources keys does not matter.

Two comments in the pipeline described a field a launch cannot report as failing loudly,
which is not the rule the code applies: each declared field must be reported by at least
one launch and match wherever reported. They now say so.

New tests pin behaviour that survived mutation before: compile grouping in
agreement.verify by library and toc key rather than object digest, the desk-check reader
taking each launch's object from its own toc key, and launch order carrying no meaning in
packing, shipping and verification. The shared _restamp test helper moves to
pack_helpers.

ALMIOPEN-2973
The probe derive tool prefixes each launch's spec fields with its launch name and keys a
compile group by launch, and both tools sort launches by name. Existing tests passed with
the prefix removed, the launch dropped from the group key, or either sort removed. New
cases put the varying field in the launch that sorts first, separate two kernels that
differ only in launch names, and permute the authored order of sources for derive and
assert. The assert tool's header now states that the kind, digest, signature and symbol
checks apply to each sources entry.

ALMIOPEN-2973
…unch sets

The descriptor validator's stub handler declares the launch set of a pack's first kernel,
so a pack whose kernels name different sets loads its engine but drops the odd kernel and
fails validation. A committed fixture, multi_launch_mismatch, and a round-trip test pin
that outcome and the error naming both sets.

ALMIOPEN-2973
No shipped config declares launches, so the native stub's launchNames() override and the
census arm that checks each kernel's sources were only ever checked as text. The real
compile tests now render both for a multi-launch config, compile the stub against the
plugin SDK headers, parse the census test and check that launchNames() returns exactly the
configured launches. A further test checks that verify_variant_sets gives the same verdict
whatever the order of a descriptor's sources keys. The README says what the stub declares
and that variants needing different launch counts are split into separate engines.

ALMIOPEN-2973
…ce handler

RFC 0017 section 15.5 now lists the three plugin SDK members the kernel-descriptor half
adds, launchNames() on the dispatch handler and sources on both the kernel definition and
the kernel descriptor, together with the UKD 1.1 version bump. Section 15.4 refers to
kernel slots as a separate draft RFC rather than citing a document that is not in the
tree. The ingestor-engine native-pack guide gains a worked multi-launch handler that
declares its launches, sizes the workspace between them, builds each launch with
launchKernelDefinition and buildIngestorKernelCode, and enqueues them in order.

ALMIOPEN-2973
A multi-launch kernel descriptor could author its sources entries only as rocke builds, so
a HIP or prebuilt hsaco multi-stage kernel had no way through the packer. hkp_pack now
accepts hip entries in the single-launch hip shape (source, entry, build) and hsaco entries
in the single-launch hsaco shape (file, symbol), one kind per map. Entries that share a
translation unit and build, or an hsaco file, compile or read once and share one code
object and toc key, while each launch keeps its own symbol and the signature read for that
symbol. role stays a rocke field and is refused on the other kinds, an hsaco map needs a
UKD arch as a single-launch hsaco kernel does, and embedded_source entries stay refused.

The packed descriptor records each launch's authored identity under provenance.sources
with the shared origin kind on top. Consumer agreement and its published evidence remain
rocke-only, so a declaration with metadata fields over a hip or hsaco map is refused, as
it is for a single-launch kernel of those kinds, and the desk check reports such a kernel
as unclaimed. A translation unit may export kernels no launch names.

ALMIOPEN-2973
…unch

The packaging probes asserted every sources launch against rocke effective-spec evidence
and role bindings. A kind now states whether its launches carry that evidence; for hip and
hsaco launches the assert checks archive membership, digest, symbol and the signature read
from the blob, while rocke keeps its evidence checks. Derive groups hip launches by source
and build and hsaco launches by launch name, as the docstrings now say.

ALMIOPEN-2973
…orGenerator

launches was accepted only on rocke kernel sources. A launch now inherits the kind of its
kernel source, and its overrides are the fields of that kind: source, entry and build for
hip, file and symbol for hsaco, and the existing rocke keys. role on a hip or hsaco launch
is a configuration error and embedded_source still takes no launches. verify_variant_sets
keys a hip launch by source, entry and build and an hsaco launch by file and symbol, so
two launches of one translation unit no longer collide.

ALMIOPEN-2973
…n device

The multi_launch fixture is now authored as a UKD 1.1 hip sources kernel with produce and
consume launches on one translation unit, and the end-to-end test loads what hkp_pack
produced instead of rewriting a single-launch descriptor at run time. It checks that both
launches share one code object and toc key with their own symbols before running them
through the engine. RFC 0017 now lists rocke, hip and hsaco as authored sources kinds and
states that consumer-agreement evidence stays rocke-only.

ALMIOPEN-2973
@therock-pr-bot

therock-pr-bot Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

✅ All Checks Passed — Ready for Review

Check Status Details
📝 PR Description ✅ Pass —
⛔ Forbidden Files ✅ Pass —
🧪 Unit Test ✅ Pass —
🔎 pre-commit ✅ Pass —
🚫 Draft PR 🔜 To Be Enabled —
🚩 Feature Flag 🔜 To Be Enabled —
📊 Code Coverage 🔜 To Be Enabled —
🤖 therock-pr-bot ✅ Pass —

🎉 All checks passed! This PR is ready for review.

📖 Need help? See the Policy FAQ for details on every check and how to fix failures.

🙋 Wish to Override Policy?

@therock-pr-bot

Copy link
Copy Markdown

🎉 All checks passed! This PR is ready for review.

…heir bugs

The engine-selector revision test changed only one launch's symbol, so dropping a launch's
sha256 or toc key from the digest, or keeping only the last launch, went unnoticed. It now
changes each field of each launch and expects a new revision every time. A launch name that
starts with an underscore gains a refusal row. The launch-definition test for two names
sharing one entry now checks that each name gets its own complete copy, and a device-free
case shows that each launch's recorded signature is checked against its own expected
signature before its archive is opened, replacing a cache-size assertion that could not
fail. launchKernelDefinition builds the single-launch definition without copying the
sources map it then discarded, and a loader comment uses the RFC's wording.

ALMIOPEN-2973
…rces kernels

The desk check's toc-key uniqueness compared each kernel's launches as one tuple, so a
single-launch kernel reusing one toc key of a multi-launch kernel passed. Kernels now count
as one whenever any launch of one shares a toc key with any launch of another, while the
launches of one kernel may still share a module. An unknown authored sources kind now gets
the same refusal message as every other refused kind, from one helper. The prewarm failure
message names every launch of a shared compile, and a loop variable no longer shadows a
parameter in the agreement check. A test pins that an accessor raising AttributeError fails
the observation instead of counting as unreported. README and test wording are corrected.

ALMIOPEN-2973
…e gate

An IngestorGenerator launch override of target or role set to an empty string was accepted,
and an empty target silently made that launch native. Both are now configuration errors.
verify_variant_sets gains a nesting case that differs only in a launch name, the
multi-launch validator round trip asserts that no kernel was dropped for its launch set,
and the README tool rows describe packed keys, sources entries in catalog_diff and
per-launch inventory counts.

ALMIOPEN-2973
…ch gate pending

The §15.1 example lists only kind, library and symbol for each entry, so it is now marked
as abridged. The loader check that every Launch is filled is described as arriving with
launches[], with the handler's declared launch names standing in until then, and the
state manager is named as the plugin SDK's.

ALMIOPEN-2973
…ne launch set

The pack-time launch-set check grouped kernels per KDP, but the loader resolves a dispatch
handler from the dispatch_symbol of a KDP's UDD and compares every kernel it serves against
that handler's launch names. Two KDPs that each agree with themselves but share a UDD, or
name one dispatch symbol from two UDDs, therefore packed cleanly while the loader dropped
one of them. The check now groups the shard's kernels by dispatch symbol and fails the pack
naming the symbol, each KDP and each launch set. The probe end-to-end fixture fused one
pointwise KDP into a multi-launch kernel while its siblings stayed single-launch on the same
UDD, which is exactly that shape, so the fused KDP now gets a UDD and dispatch symbol of its
own. The packaging README describes the check at handler scope and notes that it sees one
packaging root.

ALMIOPEN-2973
@codecov

codecov Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

Additional details and impacted files
@@             Coverage Diff             @@
##           develop   #14215      +/-   ##
===========================================
- Coverage    77.31%   75.93%   -1.38%     
===========================================
  Files         2893     2884       -9     
  Lines       486189   481016    -5173     
  Branches     73466    72380    -1086     
===========================================
- Hits        375882   365242   -10640     
- Misses       85488    90732    +5244     
- Partials     24819    25042     +223     
Flag Coverage Δ *Carryforward flag
TensileLite-CPP 48.92% <ø> (-1.89%) ⬇️ Carriedforward from 8946532
TensileLite-Unit 83.74% <ø> (-0.40%) ⬇️ Carriedforward from 8946532
hipBLAS 90.62% <ø> (ø) Carriedforward from 8946532
hipBLASLt 66.16% <ø> (-2.43%) ⬇️ Carriedforward from 8946532
hipCUB 82.68% <ø> (ø) Carriedforward from 8946532
hipDNN 86.92% <ø> (+<0.01%) ⬆️
hipFFT 42.56% <ø> (-0.62%) ⬇️ Carriedforward from 8946532
hipRAND 76.12% <ø> (ø) Carriedforward from 8946532
hipSOLVER 69.67% <ø> (ø) Carriedforward from 8946532
hipSPARSE 86.99% <ø> (-0.04%) ⬇️ Carriedforward from 8946532
rocBLAS 68.72% <ø> (-0.23%) ⬇️ Carriedforward from 8946532
rocFFT 46.05% <ø> (-1.31%) ⬇️ Carriedforward from 8946532
rocRAND 57.31% <ø> (-0.01%) ⬇️ Carriedforward from 8946532
rocSOLVER 76.74% <ø> (ø) Carriedforward from 8946532
rocSPARSE 77.16% <ø> (-6.39%) ⬇️ Carriedforward from 8946532
rocSPARSE-integration ?
rocSPARSE-unit ?
rocThrust 93.15% <ø> (ø) Carriedforward from 8946532

*This pull request uses carry forward flags. Click here to find out more.
see 390 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

…f in the launch-set check

The launch-set check looked up every KDP's UDD and failed with a KeyError on a KDP whose
dispatch names no UDD of the root, which the packer accepts (a null dispatch, as the
minimal pack roots in the packer tests author). Such a KDP has no handler it could share,
and the loader refuses its pack outright, so the check now holds it to one launch set on
its own and names it in the refusal. Two KDPs that both name no UDD are not grouped.

ALMIOPEN-2973
…inters

unsortedDefinitions returns pointers into the state manager's own definitions rather than copies, so the multi-launch end-to-end test holds the kept kernels as pointers and dereferences the one it inspects before the state manager moves into the engine.

ALMIOPEN-2973
BradPepersAMD added a commit that referenced this pull request Oct 25, 2026
RFC 0021 §3 (kernel slots, draft #13839) names "one UKD whose code object holds
the dependent kernels, launched by symbol names its KMD records" as an accepted
alternative to RFC 0017 §15.1 `sources`, with a split-KV kernel and its
reduction as the example: FlyDSL's decode and RMSNorm backward objects. The
note now says so, and that a move to hsaco `sources` entries (#14215) is
optional.

JIRA ID: ALMIOPEN-2953

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…IOPEN-2973/follow-ups

# Conflicts:
#	dnn-providers/hip-kernel-provider/CMakeLists.txt
#	dnn-providers/hip-kernel-provider/descriptor-packaging/README.md
#	dnn-providers/hip-kernel-provider/descriptor-packaging/cmake/HkpPackaging.cmake
#	dnn-providers/hip-kernel-provider/src/engines/kernel_ingestor_engine/test_descriptors/README.md
#	dnn-providers/hip-kernel-provider/src/tests/engines/kernel_ingestor_engine/CMakeLists.txt
#	projects/hipdnn/tools/IngestorGenerator/README.md
A multi-launch kernel carries its launches in `sources` and leaves `source` default, and a
default KernelSource reads as an EMBEDDED_SOURCE kernel naming no file. A reader that
looked at `source` alone therefore saw an embedded_source kernel. Plan saving did: it
refused a multi-launch plan as having source kind 'embedded_source', and the engine's
serialization behaviour note took the same wrong path to the right answer.

Descriptors.hpp gains two helpers that look at `sources` first. singleLaunchSource()
returns the one source of a single-launch kernel and nullptr for a multi-launch kernel, for
a reader that needs exactly one code object. allLaunchSources() asks a question of every
launch, whatever the kernel's shape. Plan capture, the serialization behaviour note and
buildForSourceKind read through singleLaunchSource(), and the state manager's adaptability
check through allLaunchSources(). Capture now refuses a multi-launch kernel for having
several launches. The selector digest in MakeEngine keeps reading both fields as they are,
since existing selector revisions hash them.

ALMIOPEN-2973
singleLaunchSource() returns the address of the kernel's own `source`
member, and its const reference parameter binds a temporary, so a caller
that passes one keeps a dangling pointer. The comment now says the result
is valid only while the kernel is and that a temporary must not be passed.

ALMIOPEN-2973
…s launches

The native-pack multi-launch sketch copied the workspace pointer into a
local because launch() takes its arguments by address. launch() takes a
forwarding pack and the address of its own parameters, so any expression
works, as the same calls show by passing `in.ptr` and `out.ptr` directly.
The sketch now passes `workspace` to both launches and says in the order
comment that decode writes the slice and merge reads it.

ALMIOPEN-2973
The notes under the native-pack multi-launch sketch restated the section
intro (the state manager drops a kernel with another launch set, the
handler owns launch order) and the LaunchKernelDefinition.hpp contract (the
INVALID_VALUE cases). They now list only what neither says: that the
generator refuses mismatched launch names, so another launch set needs its
own engine, that the workspace is not zeroed, and that launchNames() is
provisional. The helper list names `Binding`, which the sketch uses without
defining, and the section points at Gfx1151WmmaAttentionNative.cpp as a
shipped handler.

ALMIOPEN-2973
…epare() TODO

The generated native stub's multi-launch prepare() TODO said hkp_pack
compiled the dialect's rocke kernels to KPACK. The branch is selected by
the presence of launch names, which hip and hsaco kernels now carry as
well, so the comment says that hkp_pack compiled or packed every launch to
KPACK, whether rocke, hip or hsaco.

ALMIOPEN-2973
… hsaco declarations

The packaging README's provenance note for hip and hsaco `sources` UKDs
said one declaration is both refused and reported unclaimed. The packer
refuses a declaration that states `metadata_fields` over such a UKD, while
the desk check reports the kernel as unclaimed for a declaration without
them. The note now names the two cases separately.

ALMIOPEN-2973
… its handler

MultiLaunchHarness declared its handler, then its symbol scope, then its
scratch tree, while its comment said the tree outlasts both. Members are
destroyed in reverse order, so the tree was removed first, while the
handler and the registered symbols that point at it were still alive. The
tree is now declared first, so it is removed last, as the comment says.

ALMIOPEN-2973
…serialization note

supportsExecutionPlanSerialization() refuses a set holding a kernel with a
`sources` map, as captureIngestorPlan() cannot save one, but no test built
such a kernel. The new case takes a saveable single-kpack set, gives its
kernel two kpack launches while leaving `source` kpack, and expects false,
so a gate that read `source` instead of the launches would fail it.

ALMIOPEN-2973
Edits to the IngestorGenerator README launches paragraph, the
KernelSource.launches comment and the _build_launches docstring left one
line far past its neighbours' width and one orphaned short line. The three
passages are rewrapped to the width around them, with no change in
wording.

ALMIOPEN-2973
…k by _launch_signature

The packer's toc_key collision check built a single-launch UKD's input
signature inline, per producer, beside _launch_signature(), which builds
the same tuples for each launch of a `sources` UKD. A producer or field
added to one copy and not the other would let a collision through on that
path. Both paths now call _launch_signature(); the tuples it returns for
rocke, hip and hsaco are the ones the inline code built, so the check
behaves as before.

ALMIOPEN-2973
…ers from pack_helpers

test_hkp_pack_sources_hip_hsaco.py defined its own `ARCH`, `_read` and
`_load_kpack`, each identical to the one pack_helpers already provides to
the other packer tests. The module now imports them, so a change to the
shared arch or kpack loading reaches these cases too.

ALMIOPEN-2973
…and-in

The rocke and the hip/hsaco launch probe tests each carried their own copy
of the loader that imports hkp_probe_assert and of the kpack archive
stand-in its checks read, and the derive-root tests carried a third copy of
the loader. probe_support, which the probe tests already import, now
provides `tool_module()` and `StandInArchive`, and the three modules use
them. Each test module keeps its own fixture constants, signatures and
descriptor builders.

ALMIOPEN-2973
…est setups once

The packer refused an hsaco UKD with no `arch` in two places, one for a
single launch and one for a `sources` map, with text differing by one word.
_require_hsaco_arch() now holds the check, its reason and its message for
both. The desk-check tests that read each launch out of a stand-in archive
built the same fake kpack module twice and now share one helper, and the
derive-root tests build a rocke `sources` UKD through the same
_sources_ukd() as the hip and hsaco ones.

ALMIOPEN-2973
@GarbyGilbertAMD
GarbyGilbertAMD marked this pull request as draft October 27, 2026 14:56
@GarbyGilbertAMD
GarbyGilbertAMD marked this pull request as ready for review October 27, 2026 17:29
…IOPEN-2973/follow-ups

# Conflicts:
#	projects/hipdnn/docs/rfcs/0017_UniversalKernelDescriptor.md
…IOPEN-2973/follow-ups

# Conflicts:
#	projects/hipdnn/plugin_sdk/include/hipdnn_plugin_sdk/ingestor/Descriptors.hpp
@GarbyGilbertAMD
GarbyGilbertAMD enabled auto-merge (squash) October 29, 2026 21:40
@GarbyGilbertAMD
GarbyGilbertAMD merged commit 587f994 into develop Oct 30, 2026
175 of 177 checks passed
@GarbyGilbertAMD
GarbyGilbertAMD deleted the users/ggilbert/ALMIOPEN-2973/follow-ups branch October 30, 2026 01:15
@assistant-librarian

Copy link
Copy Markdown
Contributor

TheRock Submodule Bump Activity

Newest first

adickin-amd pushed a commit that referenced this pull request Oct 30, 2026
…ward (RDNA, CDNA) (#14111)

JIRA ID: ALMIOPEN-2953, ALMIOPEN-2954, ALMIOPEN-2955

Supersedes #13712, #13713 and #13714.

## Summary

Adds **FlyDSL** as a second kernel source for the hip-kernel-provider's
kernel ingestor, beside rocKE: a pipeline that ships prebuilt FlyDSL
code objects, and eight engines on it.

| Area | Engines | Targets |
|---|---|---|
| RMSNorm | `hipkernel:flydsl_rmsnorm` (inference and training forward),
`hipkernel:flydsl_rmsnorm_bwd` (dx, dgamma) | gfx11-generic,
gfx12-generic, gfx90a, gfx942, gfx950 |
| SDPA forward, RDNA | `hipkernel:flydsl_sdpa_rdna`,
`hipkernel:flydsl_sdpa_rdna_decode`, `hipkernel:flydsl_sdpa_aiw` (gfx12
only) | gfx11-generic, gfx12-generic |
| SDPA forward, CDNA | `hipkernel:flydsl_sdpa_cdna`,
`hipkernel:flydsl_sdpa_cdna_decode`,
`hipkernel:flydsl_sdpa_cdna_dualwave` (gfx950 only) | gfx90a, gfx942,
gfx950 |

## How it works

- **Prebuilt objects, no compiler at build or run time.** FlyDSL kernels
are compiled ahead of time into code objects (`.hsaco`).
`flydsl/gen_descriptors.py` generates their descriptors as a `FlyDSL/`
bundle, and the provider's existing packer puts them in each arch's
kpack shard. Neither the build nor the runtime needs FlyDSL, a kernel
compiler or Python at run time.
- **Objects live in DVC.** Each `FlyDSL/<op>/<target>/` directory (1,453
objects, about 29 MB) is a DVC output on the `ingestor` remote that
rocKE's descriptors use; git holds the 22 `.dvc` sidecars, the op-level
descriptors, the generators and docs. Fetch with `dvc pull -r ingestor
dnn-providers/hip-kernel-provider/src/engines/kernel_ingestor_engine/descriptors/FlyDSL/*/*.dvc`.
The provider's configure-time DVC check covers FlyDSL: a missing
directory warns and that target ships no FlyDSL kernels;
`HIPKERNELPROVIDER_REQUIRE_DVC_DESCRIPTORS=ON` (CI, release) makes it an
error.
- **Integrity.** Each `manifest.json` records every object's SHA256 and
a digest of that op's own sources. `gen_descriptors.py --check` runs
before every pack and fails on any mismatch, so a source edit without
regeneration fails the build; `check_shards.py` verifies every shard
after the pack. Regeneration is byte-reproducible with the pinned
toolchain (`REGEN.md`).
- **Generic targets.** RDNA objects are built once for `gfx11-generic` /
`gfx12-generic` and copied into every member arch's shard.
- **Runtime arguments.** Shapes, strides, head counts, scale, epsilon,
mask bounds, bias strides and the LSE output are kernel arguments, so
one object serves every shape of its class. Only tiling, head-dim tiers
and measured RMSNorm widths are baked.
- **Declines.** Each matcher gates every graph field it reads and
declines everything else, so another engine gets the plan.
`flydsl/COVERAGE.md` lists every accept and decline rule with its test.

## What each engine serves

- **RMSNorm** (153 objects per target): bf16, f16, f32, and bf16/f16
with an f32 scale; training forward writes a per-row f32 inv_rms; any
finite epsilon, fixed or pass-by-value; the frontend's normalized-axes
rule (including cuDNN's `x {B*S, D, 1, 1}` layout). Backward is FlyDSL's
deterministic two-stage kernel (dgamma bitwise reproducible). Baked
widths were kept only where they measured at least 15% over the generic
tier on two archs.
- **SDPA RDNA:** bf16/f16 at head_dim 64/96/128/256 plus generic tiers
for any multiple of 8 up to 256; causal at either corner, bands, sliding
windows; additive bias (f32 or the query dtype, any broadcast);
attention sinks; MLA 192/128 and wide single-KV-head decode (576/512,
512/512); MHA/GQA/MQA.
- **SDPA CDNA:** bf16/f16 at head_dim 64/128/256 with bucket objects
between (gfx90a also 96/160/192/224); MLA 192/128 and absorbed-MLA
decode (576/512); bias and sinks; BSHD, BHSD and packed QKV strides.
Each class ships a default tile plus measured companion tiles.
- **Same answer on every family.** RDNA, CDNA and aiw give the same
result at the edge cases (keyless rows, −inf and lowest-finite bias
rows, NaN rows, sinks, decode splits), matching PyTorch and hipDNN's
reference (`COVERAGE.md` §5.7).
- **`left_bound`** follows hipDNN's cuDNN meaning (#14483): `L` keeps
the L keys ending at the diagonal; the kernels receive `L - 1`, and 0
declines.

## Build flag and CI

- `HIPKERNELPROVIDER_ENABLE_FLYDSL` is **OFF by default**, like rocKE,
and takes effect only with `HIPDNN_ENABLE_KERNEL_INGESTOR=ON`. A default
rocm-libraries build is unchanged and needs no `dvc pull`. TheRock turns
FlyDSL on through its `HIPKERNELPROVIDER_ENABLE_FLYDSL` flag (default
ON, ROCm/TheRock#9615) together with the ingestor (TheRock #9375), and
can turn it off there; the hipDNN superbuild CI passes
`-DHIPKERNELPROVIDER_ENABLE_FLYDSL=ON`.
- FlyDSL engines and tests compile whenever FlyDSL content exists,
independent of `GPU_TARGETS` (TheRock's multi-arch build ships one
shard's host half to every arch); device tests decide at run time
whether the device's shard is staged. Packing, the shard check and the
census follow the requested archs.
- `THIRD_PARTY_LICENSES.md` (FlyDSL Apache-2.0, AITER and AOTriton MIT)
installs under `share/doc/hip-kernel-provider/flydsl/`; TheRock packages
it through the `doc` component added by ROCm/TheRock#9476.
- This PR's TheRock Multi-Arch CI builds FlyDSL, runs its device tests
and runs the FlyDSL integration entries on Linux gfx94X and Windows
gfx110X once its TheRock pin includes ROCm/TheRock#9615.

## Changes outside `flydsl/`

- Provider `CMakeLists.txt`: the option, `add_subdirectory(flydsl)`
under the ingestor gate, and the DVC check extended to FlyDSL.
- `HkpPackaging.cmake`: `FlyDSL` in `HKP_DESCRIPTOR_FAMILIES`.
- Ingestor: one pack-table entry and module cache per engine; natives
under `kernel_ingestor_engine/packs/Flydsl*`, with shared headers for
RMSNorm, RDNA SDPA, CDNA SDPA and both SDPA families.
- `descriptors/FlyDSL/`: op-level descriptors, `.dvc` sidecars and
per-target `SOURCE.md`.
- Tests: `main.cpp` adds the product shard as an additive descriptor
root when FlyDSL is active; one engine suite and one census suite per
engine, plus a per-object SDPA suite; `TestContainer`'s engine bound
raised from 8 to 32.
- Integration suite: one external integration entry per FlyDSL engine
and architecture (55), pinned with `--test-engine`, checked by the GPU
reference executor against the shared RMSNorm, RMSNormBackward and
SdpaFwd bundles, routed into the architecture's census shard and gated
on FlyDSL content. Each entry's generated TOML skips every other FlyDSL
architecture, so a family package (gfx1100–gfx1103) runs each suite
once. Category YAMLs
`hipkernel_flydsl_*_test_categories_integration.yaml`; the two
4096-token fp16 causal bhsd SdpaFwd cases run from the comprehensive
tier up. Support claims recorded for gfx1151.
- rocKE test fixes for two Windows CI failures: the GPU-reference
worker's temporary directory removal retries while Windows releases a
killed worker's handles, and `test_lowers_and_compiles_without_scratch`
gets its own 180 s limit (it ran ~54 s of 60 s).

`flydsl/` holds the vendored kernel sources at pinned commits (FlyDSL,
AITER, AOTriton; every local modification listed in each file's header
and in the attention READMEs), the generators, `gen_descriptors.py`,
`tools/check_shards.py`, the drift-guard tests, and `README.md`,
`REGEN.md` and `COVERAGE.md`.

## Risks

| Risk | Mitigation |
|---|---|
| TheRock ships FlyDSL on merge | TheRock's
`HIPKERNELPROVIDER_ENABLE_FLYDSL` flag switches it off; this PR's
TheRock CI built and tested FlyDSL, and a run pinned to TheRock main
passed on gfx942, gfx950 and gfx110X |
| Prebuilt objects drift from their sources | Per-object SHA256 and
per-op source digest checked before every pack; drift-guard tests prove
the checks refuse tampered trees |
| An engine runs a graph it cannot compute | Every read field is gated,
with one decline test per rule, mutation-checked |
| One object set per generic family | Objects verified as
`gfx11-generic` / `gfx12-generic`; every member shard verified after
pack; gfx1150 and gfx1153 have no device run (same objects as gfx1151
and gfx1100) |
| A device suite passes with no objects staged | Device cases fail
rather than skip on an arch that ships their family; shard censuses fail
on an empty shard |
| Selection between overlapping engines | Static per-object priority
today; autotune measures every applicable engine and object; UHD
heuristics are a follow-up |

**Known deviation:** RMSNorm backward and the two split-KV decode
engines launch a second kernel compiled into the same object, named in
KMD metadata (`reduce_symbol`, `merge_symbol`), instead of RFC 0017
§15.1 `sources` entries. RFC 0021 §3 names this form as an accepted
alternative (`COVERAGE.md` §8).

## Testing

- **Strategy:** host tests for every matcher, score and decline rule,
checked against compiled mutants; GPU launches against a
double-precision host reference; a per-object suite that launches every
shipped object (every shape class in its `Full/` tier); shard censuses;
`gen_descriptors --check` before pack and `check_shards` after.
- **CI:** all required checks green at `fcb674c8766`, with FlyDSL device
tests on Linux gfx94X and Windows gfx110X (FlyDSL ON by default then).
- **Device runs on the shipped objects:** gfx950, gfx942, gfx90a,
gfx1201, gfx1200 and gfx1100 ran the default and `Full/` tiers,
launching every object of their families, with 0 failures; gfx1151 runs
the default tier. With an empty descriptor root every device case of the
arch's families fails.
- **Local, this head (gfx1151):** 841 FlyDSL, container and ingestor
gtests passed (62 skipped need other GPUs); census, FlyDSL and
name-validation CTests pass; the FlyDSL integration entries pass the
quick tier (rmsnorm 12, rmsnorm_bwd 5, sdpa_rdna 14, sdpa_rdna_decode 13
cases verified, 0 failed).
- **After the next TheRock pin move:** a Multi-Arch run of this head
with the TheRock pin moved to TheRock main plus #9615 and
ROCm/TheRock#9619 (test branch, not merged) built FlyDSL and passed
every hipkernelprovider, hipDNN and integration job on gfx950, gfx942
and Windows gfx110X. The FlyDSL integration entries verified 9–12 cases
per SDPA engine and 12/5 per RMSNorm engine, 0 failed; only the runner's
own architecture's entries ran.
- **Regeneration:** every op on every target is byte-identical to the
shipped objects; `diff_upstream.py` shows only recorded modifications.
- **Tiers:** quick, standard and comprehensive run everything but
`Full/`; the full tier adds every object on every shape class.

## Follow-ups

- Support claims for the architectures beyond gfx1151 (harvest from CI
once the TheRock pin includes #9615), and UHD heuristics for the FlyDSL
engines.
- Move the two-launch objects to `hsaco` multi-launch `sources` entries
now that #14215 has landed.
- RMSNorm: bias/dbias, strided rows, fusions (residual add, FP8 output,
zero-centered gamma), baked widths ≤ 2048, backward above 16384.
- SDPA: padding/varlen, exact head-dim 96/160/192/224 objects on
gfx942/gfx950, a d512 prefill object, the deferred performance items in
`COVERAGE.md` §7.5, and upstreaming the kernel modifications.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
AviralGoelAMD added a commit that referenced this pull request Nov 2, 2026
Brings in #13955 as merged (the stacked copy drops out), #14367, #14276,
#14215, #14109, #14111, #13897, #14679 and the rest of develop.

Resolutions:
- Parity emitters: develop's #14367 added gfx942 tiled-3D configs 18 and 19;
  this branch's strided decode configs move from 18-27 to 20-29 in the .py and
  .c, and the C strided switch moves to idx >= 20. Golden re-recorded for the
  family only: 0-19 unchanged in every flavor, 20-29 added.
- test_registry_regeneration: keep the per-engine parametrization and adopt
  develop's stable-id, byte-for-byte g2 and --expect-ids g3, with the shipped
  folder taken per engine instead of the gfx950 globals.
- Representative golden: take develop's per-family shards (#14679).
- CMake, IngestorPacks.hpp, READMEs: keep both sides; SUPPORT_MATRIX_OVERVIEW
  re-rendered from the merged claims.
BrianHarrisonAMD added a commit that referenced this pull request Nov 2, 2026
…g (ALMIOPEN-2922) (#13972)

## Summary
Implements [RFC
0021](https://github.com/ROCm/rocm-libraries/blob/develop/projects/hipdnn/docs/rfcs/0021_KernelSlots.md)
(kernel slots). An engine can run several kernels in a fixed order, and
each position (a slot) picks its kernel independently. The first
intended user is split SDPA backward (prep, dK/dV, dQ).

JIRA ID : ALMIOPEN-2922

## Risk Assessment
Risk 3: a new feature path in the plugin SDK, behind
`HIPDNN_ENABLE_KERNEL_INGESTOR`. That flag is OFF by default in hipDNN
and ON in TheRock.

Engines without slots are unchanged. Golden tests pin their knob ids,
selector revision and winner records, and their packed bundles match
`develop` byte for byte. Public API changes are additive, apart from the
source changes listed in RFC 0021 section 10.

## ASIC Coverage
The change is architecture-independent host code. It was tested on the
host with the GPU hidden, and on a gfx90a device for the device-gated
tests (gfx950 for an earlier head). A local build targeting gfx90a,
gfx950 and gfx1151 runs every packed-load test. CI covers Linux and
Windows superbuilds and TheRock gfx94X, gfx950, gfx110X and gfx125X
builds; the Windows superbuild currently fails at configure on a
`develop` issue (#14801).

## Testing Summary
Results are for this head: the single feature commit, rebased onto
`develop` f755808.

Host suites (Linux, flag ON, GPU hidden):

| Suite | Result |
|---|---|
| `hipdnn_plugin_sdk_tests` | 1637 run, 0 failed, 15 skipped
(device-gated or locale) |
| hipDNN ctest: SDK, validator, generator, bench and `uhd_gen`
(required, not skipped) | 88/88 |
| hip-kernel-provider ctest: gtest suites, `hkp_pack` pytest and
packaging probes (provider-wide GPU integration tiers not run) | 67 run,
0 failed, 1 skipped (environment) |
| `hkp_pack` and packaging-probe pytest, run directly | 386 and 182
passed |

Device-gated tests on gfx90a:
- Plugin SDK stall, benchmark and timer tests: 45/45.
- `hip_kernel_provider_tests`: 1179 passed, 3 skipped (a device
code-object capture, and the gfx950 and gfx1151 fixture loads, which the
three-arch build runs: 10/10 packed-load tests). This includes
`TestMultiLaunchEndToEnd`.
- `hip_kernel_provider_integration_tests`: 35/35, including the
`kernel_ingestor_engine` suites.

Not tested:
- Real slotted kernels; the fixtures are synthetic.
- `hipdnn_bench --sweep` on a slotted engine.
- The RFC section 11 separability check.

Like the existing `uhd_gen` tests, the slot tests skip in CI because CI
lacks pandas, pyarrow and lightgbm (#14623). They pass locally.

## Testing Checklist
- [x] Host suites above - Status: Passed
- [x] Device-gated SDK and HKP tests - Devices: gfx90a (gfx950 for an
earlier head) - Status: Passed
- [x] pre-commit - Status: Passed
- [ ] hipDNN superbuild CI, Linux and Windows - Status: Linux running;
Windows fails at configure on a `develop` FlyDSL census-shard error, not
from this change (fix: #14801)
- [ ] TheRock multi-arch CI - Status: Running on the new head

## Technical Changes
- **Plugin SDK:**
  - UED, KDP and UHD 1.1 describe slots.
- Each slot has its own catalog, ranker, `<slot>.<field>` knobs and
winner records.
- A slot program runs the picks over one shared workspace.
`SlotProgramBenchmark` times whole programs, and `winners.jsonl` v3
records the results.
- **Composition with existing features:**
- Slots work with multi-launch kernels, pointer catalogs, staged
applicability and the stall-restart benchmark policy.
- A slot's kernels may be rocKE, hip or hsaco multi-launch kernels
(#14215); `launches` and the launch-set checks apply per slot. The
gfx950 hsaco fixture's `dq` slot is a two-launch hsaco `sources` kernel.
  - Regenerated slotted bundles keep their descriptor ids (#14109).
  - Slotted plans are not serialized (RFC 0021 section 11).
- **RFCs:** RFC 0017 links RFC 0021 and carries the slot edits RFC 0021
lists.
- **Tooling:**
  - `uhd_gen --slot` trains and promotes one slot's ranker.
- IngestorGenerator, `hipdnn_validate_descriptors` and `hipdnn_bench`
accept slotted engines.
- **`hkp_pack`:** packs slotted engines and rejects invalid slot
configurations it can detect statically.
- **Shared rule corpus:** the `trained_against` slot-provenance rules
are one JSON corpus run by the C++ parser, the packaging schema,
`hkp_pack` and `uhd_gen`.
- **Test packaging:** fixtures built for one arch (gfx950 hsaco, gfx1151
multi-launch) pack only when the build targets that arch. On other
builds, packaging probes check that they pack.
- **Skills:** the `hipdnn-ingestor-engine` skill names RFC 0017 by
repository path, so `validate-skills.py` passes.
- **Behavior changes visible on unslotted engines:**
  - Ingestor log lines now name the engine.
- A cached decline logs at INFO instead of TRACE. Logging is off by
default.

## Known Issues
- PR CI does not build for gfx950 or gfx1151 on Linux, so the
packed-load tests of the two single-arch fixtures do not run there. The
gfx1151 test would run on the Windows superbuild, which currently fails
at configure on a `develop` issue (#14801); both ran in a local build
targeting gfx90a, gfx950 and gfx1151 for this head. Until CI covers
these arches, changes to those fixtures need a build that targets them.
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.

2 participants