Skip to content

ALMIOPEN-2502: harden winner cache follow-ups - #11804

Merged
SamuelReeder merged 7 commits into
developfrom
users/sareeder/almiopen-2502-followups
Sep 14, 2026
Merged

SamuelReeder merged 7 commits into
developfrom
users/sareeder/almiopen-2502-followups

Conversation

@SamuelReeder

@SamuelReeder SamuelReeder commented Sep 8, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Harden the in-process winner cache follow-ups from the ALMIOPEN-2502 review. Avoid graph-key construction on the cold no-op path, reject unidentified devices, verify retained graph buffers, and keep generated cache-key hashing and equality consistent for floating-point values.

JIRA ID : ALMIOPEN-2502

Risk Assessment

Risk level 3. The change touches winner-cache lookup, graph-key validation, and generated cache-key equality in the plugin and FlatBuffers SDKs. The behavior is covered by focused unit tests, fail-before/pass-after evidence, and the full affected SDK test suites. It does not add a provider operation or architecture-specific kernel path. KernelIngestorStateManager::mightHaveWinnerFor moved from private to public so GenericPlanBuilder can call it; it is header-only and templated, so this is not an ABI change, but it is a new public surface. A second review pass found a real correctness defect this PR's own tests did not cover (a rejected empty-architecture catalog could be cached and served for a later, resolved device); it is fixed and now has fail-before/pass-after regression coverage.

ASIC Coverage

The change is architecture-independent host-side cache and validation logic. It does not change kernel support, dispatch selection for a valid device, or provider registration. Standard PR CI and host ASAN coverage are sufficient; no specific-ASIC run or full multi-arch sweep is required.

Testing Summary

  • Code-generation unit tests: 43 tests passed.
  • hipDNN plugin SDK, FlatBuffers SDK, and cache-key code-generation suites: 3/3 passed after rebasing onto current develop and after the second-pass catalog-cache fix.
  • Focused malformed-buffer, NaN, empty-architecture, and cold-miss regressions passed.
  • Configure and build passed with HIPDNN_ENABLE_KERNEL_INGESTOR=ON, ENABLE_CLANG_FORMAT=ON, and ENABLE_CLANG_TIDY=ON.
  • Changed-file pre-commit hooks passed in the build container.
  • Host ASAN CI was requested with the ci:host-asan label; the workflow is pending.

Fail-Before / Pass-After Evidence

The baseline runs used a temporary tree with the new tests retained and the affected product files restored from origin/develop.

  • Generator defects: the focused baseline command cd projects/hipdnn/scripts && python3 -m unittest test_gen_cache_key.TestPortableByteOperations.test_a_float_field_compares_its_object_representation test_gen_cache_key.TestPortableByteOperations.test_a_float_vector_compares_elements_by_object_representation test_gen_cache_key.TestUidCanonicalization.test_a_second_domain_shaped_candidate_is_rejected test_gen_cache_key.TestUidCanonicalization.test_more_than_one_domain_annotation_is_rejected -v produced 3 failures (scalar float comparison, float-vector comparison, and second domain-shaped candidate); the duplicate annotation test passed. The same four tests pass on this tree.
  • Graph-key defects: the baseline command hipdnn_flatbuffers_sdk_tests --gtest_filter="TestGraphContentKey.TwoGraphsCarryingTheSameNanFloatComparePairwiseEqual:TestGraphContentKey.TwoGraphsCarryingDifferentNanPayloadsCompareUnequal:TestGraphContentKey.AGraphWithMalformedBytesYieldsAnUnusableKey" failed the identical-NaN test and then crashed with Segmentation fault in the malformed-buffer test. The patched command passes all 3 tests.
  • Empty architecture: the baseline command hipdnn_plugin_sdk_tests --gtest_filter="TestIngestorWinnerCacheStateManager.AnEmptyArchNameYieldsAnEmptyCatalog" failed with Actual: false, Expected: true; the patched command passes.
  • Catalog cache poisoning: sortedCatalog() cached a rejected, empty catalog under a key ({graph, device ordinal}) that ignores architecture; the extended AnEmptyArchNameYieldsAnEmptyCatalog (restoring the architecture after the empty-arch call) failed with Actual: true, Expected: false against the code before this fix; the patched command passes.
  • Cold miss: the baseline command hipdnn_plugin_sdk_tests --gtest_filter="TestIngestorGenericPlanBuilder.ASecondColdMissWithBenchmarkingOffDoesNotReadGraphBytes" reported bytesCalls->load() Which is: 1, while the patched command reports 0 and passes.

Testing Checklist

  • Code-generation tests - python3 -m unittest discover -s projects/hipdnn/scripts -p "test_gen_cache_key.py" -v - Status: Passed (43 tests)
  • hipDNN SDK unit suites - ctest --test-dir build/projects/hipdnn --output-on-failure -R '^(hipdnn_plugin_sdk_tests|hipdnn_flatbuffers_sdk_tests|hipdnn_cache_key_codegen_tests)$' - Status: Passed (3/3)
  • Focused regressions - hipdnn_flatbuffers_sdk_tests --gtest_filter='*Malformed*:*Nan*', hipdnn_plugin_sdk_tests --gtest_filter='*AnEmptyArchNameYieldsAnEmptyCatalog', and hipdnn_plugin_sdk_tests --gtest_filter='*ASecondColdMissWithBenchmarkingOffDoesNotReadGraphBytes' - Status: Passed
  • Build and lint gates - cmake --fresh --preset hipdnn -B build -DHIPDNN_ENABLE_KERNEL_INGESTOR=ON and cmake --build build - Status: Passed
  • Changed-file pre-commit hooks - pre-commit run --files $(git diff --name-only origin/develop...HEAD) - Status: Passed
  • PR CI - GitHub PR checks - Status: Pending

Technical Changes

  • Update winner-lifetime documentation to describe per-(graph, device) persistence and disk caching.
  • Guard WinnerKey construction with the cheap disk-aware winner probe and reject empty device architecture names.
  • Restore BenchmarkPlan private state.
  • Emit portable std::memcpy, bitwise float/double equality, and bitwise float/double vector equality; reject ambiguous domain-shaped cache-key vectors.
  • Verify retained graph bytes before calling FlatBuffers GetRoot.
  • Add regression coverage for malformed buffers, NaN payloads, empty architecture names, cold misses, generator portability, and ambiguous domains.
  • Correct the cache-key seam and IGraph virtual-order comments.
  • Restore a closing brace the generator's string-vector branch was missing (the new float/double branch had absorbed it, leaving an unterminated if in emitted code that only compiles today because no schema reachable from Graph has a string-element vector); add a test asserting brace balance across every vector element kind so the defect fails a test rather than only an assertIn on body text.
  • Run the duplicate-cache_uid_domain-annotation check before the candidate-ambiguity check, so the more specific diagnosis fires for the natural mistake of annotating two domain-shaped fields.
  • Stop silently wrapping to the last schema object when a domain candidate's element index is missing; skip the candidate or raise instead.
  • Tighten the float/double memcmp generator tests to require != 0 in the emitted condition, and give the C++ graph-content-key test fixture a required (non-optional) TensorValue case so that scalar-Float comparison site gets real byte-level coverage.
  • Guard sortedCatalog() with the same reject condition as catalogFor(), so a context with an unresolved device or empty architecture never writes its rejected, empty catalog into _catalogCache under the same (graph, device ordinal) key a later, resolved call for that device would reuse.
  • Narrow docs/PluginDevelopment.md's claim that a primed benchmarking plan "re-samples every candidate on each execute"; BenchmarkPlan resolves once per plan lifetime.

@therock-pr-bot

therock-pr-bot Bot commented Sep 8, 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

therock-pr-bot Bot commented Sep 8, 2026

Copy link
Copy Markdown

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

@codecov

codecov Bot commented Sep 8, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

Additional details and impacted files
@@             Coverage Diff             @@
##           develop   #11804      +/-   ##
===========================================
- Coverage    70.54%   69.42%   -1.13%     
===========================================
  Files         2810     2828      +18     
  Lines       462436   470102    +7666     
  Branches     68077    69415    +1338     
===========================================
+ Hits        326219   326332     +113     
- Misses      112673   120069    +7396     
- Partials     23544    23701     +157     
Flag Coverage Δ *Carryforward flag
TensileLite-CPP 38.50% <ø> (-7.95%) ⬇️ Carriedforward from 760fe2c
TensileLite-Unit 76.06% <ø> (+0.03%) ⬆️ Carriedforward from 760fe2c
hipBLAS 90.62% <ø> (ø) Carriedforward from 760fe2c
hipBLASLt 35.22% <ø> (-0.01%) ⬇️ Carriedforward from 760fe2c
hipCUB 82.68% <ø> (ø) Carriedforward from 760fe2c
hipDNN 87.02% <100.00%> (+<0.01%) ⬆️
hipFFT 42.66% <ø> (ø) Carriedforward from 760fe2c
hipRAND 76.12% <ø> (ø) Carriedforward from 760fe2c
hipSOLVER 68.92% <ø> (ø) Carriedforward from 760fe2c
hipSPARSE 86.99% <ø> (ø) Carriedforward from 760fe2c
rocBLAS 48.31% <ø> (ø) Carriedforward from 760fe2c
rocFFT 47.78% <ø> (-3.94%) ⬇️ Carriedforward from 760fe2c
rocRAND 56.91% <ø> (+<0.01%) ⬆️ Carriedforward from 760fe2c
rocSOLVER 76.83% <ø> (ø) Carriedforward from 760fe2c
rocSPARSE 74.61% <ø> (ø) Carriedforward from 760fe2c
rocThrust 91.60% <ø> (ø) Carriedforward from 760fe2c

*This pull request uses carry forward flags. Click here to find out more.

Files with missing lines Coverage Δ
...ffers_sdk/flatbuffer_utilities/GraphContentKey.hpp 82.79% <100.00%> (+0.41%) ⬆️
...tbuffers_sdk/flatbuffer_utilities/GraphWrapper.hpp 77.88% <ø> (ø)

... and 93 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.

@SamuelReeder SamuelReeder added the ci:host-asan Opt-in to running multi-arch host-asan CI on a pull request label Sep 8, 2026
@SamuelReeder SamuelReeder self-assigned this Sep 9, 2026
@SamuelReeder
SamuelReeder marked this pull request as ready for review September 9, 2026 14:18
@SamuelReeder
SamuelReeder requested a review from a team as a code owner September 9, 2026 14:18
SamuelReeder and others added 4 commits September 9, 2026 16:15
- Restore the String-vector branch's closing brace, mistakenly
  absorbed by the new Float/Double elif (BLOCKING-1, confirmed by
  external review compiling the emitted header).
- Add TestEmittedBodiesAreWellFormed: assert brace balance per vector
  element kind, so a dropped brace fails a test instead of only an
  assertIn on body text (BLOCKING-2, the regression test for the above).
- Reorder cache_uid_domain validation so the duplicate-annotation
  check (declared on N fields) runs before the candidate-ambiguity
  check; the natural mistake now gets the more specific diagnosis
  (IMPORTANT-5).
- Stop wrapping to the last schema object on a missing element index
  in the domain-candidate/resolution paths; skip or raise instead
  (SUGGESTION-6).
- Tighten the float/double memcmp tests to assert "!= 0" is part of
  the emitted condition, closing a != -> > mutation gap.
- Give ContentCarryingTestGraph a required (non-optional) TensorValue
  case, so the non-optional scalar Float memcmp site gets real
  byte-level coverage instead of 0.
…OCm/rocm-libraries into users/sareeder/almiopen-2502-followups
- sortedCatalog() now mirrors catalogFor()'s own reject guard before
  computing a cache key. cacheKey() reads only graph id and device
  ordinal, never arch, so an unresolved-arch context previously cached
  its rejected, empty catalog under the SAME key a later, resolved
  call for that device reuses -- permanently hiding the real catalog.
  Reproduced fail-before/pass-after against the extended
  AnEmptyArchNameYieldsAnEmptyCatalog test.
- PluginDevelopment.md:419 overclaimed that a primed benchmarking plan
  "re-samples every candidate on each execute"; BenchmarkPlan resolves
  once per plan lifetime (TheWinnerIsResolvedOnceAcrossRepeatedExecuteCalls
  covers this). Narrowed the claim to the priming execute specifically.

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

LGTM!

@SamuelReeder
SamuelReeder merged commit eb06822 into develop Sep 14, 2026
156 of 158 checks passed
@SamuelReeder
SamuelReeder deleted the users/sareeder/almiopen-2502-followups branch September 14, 2026 14:33
@assistant-librarian

Copy link
Copy Markdown
Contributor

TheRock Submodule Bump Activity

Newest first

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci:host-asan Opt-in to running multi-arch host-asan CI on a pull request documentation organization: ROCm project: hipdnn

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants