Skip to content

feat(hipblaslt): Introduce Solution Unique ID generation foundation - #12185

Merged
dsaffars merged 12 commits into
developfrom
users/dsaffars/universal_unique_id_step_1
Oct 9, 2026
Merged

dsaffars merged 12 commits into
developfrom
users/dsaffars/universal_unique_id_step_1

Conversation

@dsaffars

@dsaffars dsaffars commented Sep 16, 2026 •

Copy link
Copy Markdown
Contributor

JIRA ID: AIHPBLAS-4733

Motivation

hipBLASLt still identifies kernels by a build-order global solution index. That index moves when logic YAML files are added, removed, or reordered, so bench logs, geko, and CI cannot tell whether a kernel itself changed or only the library layout did.

This PR is step 1 of the SolutionUID migration. It introduces a stable 64-bit SolutionUID format, YAML field placement, regeneration tooling, and a uniqueness gate. It does not backfill shipped logic YAML, does not mint UIDs during TensileCreateLibrary, and does not change runtime or bench selection.

Technical Details

Identifier. Internally SolutionUID is a uint64: (ms_since_epoch << 24) | secrets.randbits(24):

  • 40 bits: milliseconds since 2026-01-01 UTC (EPOCH_MS = 1767225600000, ~35 years of headroom)
  • 24 bits: OS-backed random (`2^24 -1 values per millisecond)

Generated in tensilelite/Tensile/Common/SolutionIdGen.py. Identity, comparison, uniqueness, and mapping use that integer. YAML and CLI print an unpadded base62 string:

  • alphabet: 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
  • writers use prefix 0u; readers also accept 0U
  • no padding; leading zeros are rejected except that zero is 0u0
  • values larger than 2^64 − 1 are rejected (same class of error as an out-of-range solution_index)
  • example: decimal 200 is 0u3E

In dict-format logic YAML the optional, unquoted field sits immediately after the local SolutionIndex:

- SolutionIndex: 0
  SolutionUID: 0u3E

encode_solution_uid / decode_solution_uid live next to generation. read_solution_uid decodes the string immediately; ensure_solution_uid / regenerate_solution_uid store the canonical 0u string.

YAML I/O only. LibraryIO.reorderSolutionsParams preserves that key order when a UID is present. Existing solutions without the field are unchanged.

Regenerate one UID (no full-repo scan):

cd projects/hipblaslt/tensilelite
python3 -m Tensile.TensileGenerateUID path/to/logic.yaml --index 5 --inplace

--index is the local SolutionIndex. Without --inplace the new canonical 0u UID is printed only.

Uniqueness CI. New component hipblaslt_library_uniqueness in .github/scripts/component_ci.py runs tox -e library-uniqueness (CPU-only, no ROCm). It scans all *.yaml under Logic/asm_full, decodes 0u/0U text, and fails on duplicate or malformed UIDs (including stored 0u0 and leftover decimal). Missing SolutionUID is ignored unless HIPBLASLT_REQUIRE_SOLUTION_UID is set; the tox env does not set it, so current YAML without UIDs still passes. The job triggers on Logic YAML, the uniqueness test, tox.ini, and component-ci-library-uniqueness.yml.

Out of scope (later PRs): repo-wide YAML backfill to 0u…, LibraryLogic winner assignment, UidMapping / MatchTable, and bench/API --algo_method uid.

Test Plan

  • Unit tests for generation, 40+24 decode, ensure_solution_uid / read_solution_uid, and the regenerate CLI (test_tensile_generate_uid.py).
  • Base62 codec: round-trip, 0u0, 0U prefix, reject leading zeros / bad characters / uint64 overflow (test_solution_uid_base62.py).
  • Concurrent uniqueness at winner scale: 8 processes × 8 IDs (test_solution_uid_concurrency.py), plus sequential generation and a 10-winner batch.
  • LibraryIO / TensileMergeLibrary tests that conversion keeps SolutionUID next to SolutionIndex with 0u fixtures.
  • Uniqueness checker: discovers all asm_full *.yaml (not only *_UserArgs.yaml); fails on duplicates and non-canonical text; does not fail on missing UIDs by default.
  • Component CI: python -m tox -e library-uniqueness from projects/hipblaslt/tensilelite.

Test Result

Local uniqueness tox (pytest --noconftest on the uniqueness test) passed with no shipped SolutionUID fields (missing UIDs are not a failure). Generator, CLI, and base62 unit tests cover the 40+24 layout, canonical 0u encode/decode, and regenerate-in-place path. The 8×8 concurrent test is sized so same-millisecond 24-bit birthday risk stays ~0.01%, not the ~0.78% of the old 64×8 batch. GitHub Component CI uniqueness will run when Logic YAML, the uniqueness test, tox.ini, or the uniqueness workflow change.

Keep the cross-process uniqueness check at a winner-scale batch so the
test is less likely to flake on same-millisecond 24-bit collisions.
@therock-pr-bot

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

@codecov

codecov Bot commented Sep 16, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

Additional details and impacted files
@@             Coverage Diff             @@
##           develop   #12185      +/-   ##
===========================================
- Coverage    72.12%   71.70%   -0.42%     
===========================================
  Files         2868     2824      -44     
  Lines       473269   467535    -5734     
  Branches     69803    69199     -604     
===========================================
- Hits        341336   335217    -6119     
- Misses      108234   108824     +590     
+ Partials     23699    23494     -205     
Flag Coverage Δ *Carryforward flag
TensileLite-CPP 49.33% <ø> (ø)
TensileLite-Unit 83.35% <100.00%> (+0.03%) ⬆️
hipBLAS 90.62% <ø> (ø) Carriedforward from 1074f03
hipBLASLt 39.34% <ø> (+0.43%) ⬆️
hipCUB 82.68% <ø> (ø) Carriedforward from 1074f03
hipDNN 87.02% <ø> (+0.36%) ⬆️ Carriedforward from 1074f03
hipFFT 42.66% <ø> (+0.15%) ⬆️ Carriedforward from 1074f03
hipRAND 76.12% <ø> (ø) Carriedforward from 1074f03
hipSOLVER 68.92% <ø> (-0.04%) ⬇️ Carriedforward from 1074f03
hipSPARSE 86.99% <ø> (ø) Carriedforward from 1074f03
rocBLAS 48.31% <ø> (+0.14%) ⬆️ Carriedforward from 1074f03
rocFFT 47.78% <ø> (-3.68%) ⬇️ Carriedforward from 1074f03
rocRAND 56.90% <ø> (-0.54%) ⬇️ Carriedforward from 1074f03
rocSOLVER 76.83% <ø> (+<0.01%) ⬆️ Carriedforward from 1074f03
rocSPARSE 74.61% <ø> (+0.54%) ⬆️ Carriedforward from 1074f03
rocThrust 91.60% <ø> (-1.55%) ⬇️ Carriedforward from 1074f03

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

Files with missing lines Coverage Δ
...blaslt/tensilelite/Tensile/Common/SolutionIdGen.py 100.00% <100.00%> (ø)
...rojects/hipblaslt/tensilelite/Tensile/LibraryIO.py 95.69% <100.00%> (+0.03%) ⬆️
...ipblaslt/tensilelite/Tensile/TensileGenerateUID.py 100.00% <100.00%> (ø)

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

Exercise missing-file, non-dict YAML, and epoch overflow branches so
TensileGenerateUID and SolutionIdGen unit coverage is complete.
The shipped logic YAML lives in the hipBLASLt product tree, so it is
missing when this test runs from installed tensilelite artifacts. Guard
it with the same skipif other corpus tests use instead of failing.

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

test_generate_solution_id_is_unique_across_sequential_calls is the one I tested for flakiness, but others may have a similar issue.

This also needs to be considered when we're going to be generating new kernels as they will likely run into this same issue depending on how numbering will be implemented.

Redraw a repeated ID inside the concurrency test so one process does not fail on a same-millisecond collision.

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

Remaining concern: guaranteeing that the generated ID is globally unique during the course of regular generation of kernels without requiring a manually activate verification and fixup pass or relying on CI to catch the issue.

Discussed offline and that concern will be addressed in one of the follow-up PRs that fully integrates an enables this feature. Approving with the understanding that this required change is within the scope of one of those follow-up PRs.

@JeniferC99

Copy link
Copy Markdown
Contributor

Cancelling the remaining gfx950 jobs on this run so the TheRock submodule bump PRs can be prioritized on the gfx950 queue.

This change does not target gfx950, and gfx950 was the only work still outstanding. Jobs that already finished are unchanged. Re-run failed jobs if you need gfx950 results before merge.

@JeniferC99 JeniferC99 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 if ci pass

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

Stable solution indices will be very nice, thanks for working on this! An agent review (https://github.com/newling/agent-public-reviews/blob/main/rocm-libraries/review_pr12185.md) has a few suggestions and fixes, please take a look.

  1. Use PyYAML instead of raw string parsing so the uniqueness check handles reordered fields, inline mappings, and comments correctly.
  2. Preserve the intended YAML field order when regenerating IDs by passing sort_keys=False to the writer.
  3. Forward the UID checker’s environment variables through tox so strict mode, custom logic directories, and worker counts take effect.
  4. Clarify the docs: UID decoding is explicit, and the later migration step makes IDs mandatory.

@dsaffars
dsaffars merged commit e487575 into develop Oct 9, 2026
204 of 207 checks passed
@dsaffars
dsaffars deleted the users/dsaffars/universal_unique_id_step_1 branch October 9, 2026 06:36
@assistant-librarian

Copy link
Copy Markdown
Contributor

TheRock Submodule Bump Activity

Newest first

Comment on lines +92 to +99
library-uniqueness:
name: "hipBLASLt library uniqueness"
needs: changes
if: needs.changes.outputs.library-uniqueness == 'true'
uses: ./.github/workflows/component-ci-library-uniqueness.yml
with:
docker_image: ${{ needs.changes.outputs.docker-image }}
linux_runner: ${{ needs.changes.outputs.linux-runner }}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use smaller runners for these tests (or move them into an existing workflow instead of adding a new workflow). 96 core machines are expensive and in short supply.

https://github.com/ROCm/rocm-libraries/actions/runs/37805607146/job/113409341093 took 3 minutes total for just 7 seconds of tests. 2m53 was just overhead checking out the repository.

cc @kailash-khalasi

tony-davis added a commit that referenced this pull request Oct 19, 2026
- R2: require caller edits only for breaking interface changes; call out external callers.
- R3: keep review read-only; run pre-commit in a throwaway checkout when reviewing.
- R4: say the base helper does not apply the high-coupling list.
- R8: shorter description, full links to the base skill, note on extends/argument-hint.
- M4/R7: add a completed retrospective review of #12185 as a worked example.

Resolves #13727

Co-authored-by: Cursor <cursoragent@cursor.com>
tony-davis added a commit that referenced this pull request Oct 19, 2026
- R2: require caller edits only for breaking interface changes; call out external callers.
- R3: keep review read-only; run pre-commit in a throwaway checkout when reviewing.
- R4: say the base helper does not apply the high-coupling list.
- R8: shorter description, full links to the base skill, note on extends/argument-hint.
- M4/R7: add a completed retrospective review of #12185 as a worked example.

Resolves #13727

Co-authored-by: Cursor <cursoragent@cursor.com>
tony-davis added a commit that referenced this pull request Oct 20, 2026
…d scripts (#13729)

Resolves #13727

## Summary

Adds a `github-ci-pr-quality` overlay on the `rocm-pr-quality` base
skill for changes under `.github/`. It tells authors and reviewers where
CI tests belong (extend an existing lane, not a new workflow per test),
how to size runners and checkout, how to treat shared state in `ci-env`,
and to read each affected project's TESTING.md before changing a lane or
gate. It also covers what a CI job checks out (the PR merge ref,
`refs/pull/<N>/merge`, so every lane tests the same tree) and requires
CI references to be updated when files move or are deleted. A matching
Copilot review instructions file loads it for `.github/**`. This is the
second of two PRs; it is stacked on the root AGENTS.md PR (#13728), so
its base is that branch until #13728 merges.

## Risk Assessment

1/5. Guidance for reviewers and AI assistants only. No workflow, script,
or build changes, and the guidance is advisory. One behavior change:
Copilot code review will start applying this guidance to PRs that touch
`.github/**`.

## Related

- Work tracking: #13727
- Depends on: #13728 (the root AGENTS.md PR, tracked in #13726)
- Cases it is designed to catch: #12185, #13623 (reverted in #13698),
and the stale paths left by #12150 (fixed in #13399)
- Review input: a skill-forge review of the PR-quality skills (findings
R2, R3, R4, R8, M4/R7 applied here; the helper findings M1, M2, M3, and
R5 are fixed in ROCm/TheRock#6653; the rest of the base-skill findings
are still open)
- Base skill: `skills/rocm-pr-quality/` in ROCm/TheRock

## Testing Summary

- `pre-commit` on the changed files passed. Every workflow, script,
action value, and path the skill cites was checked against
`origin/develop`.

## Testing Checklist

- [x] pre-commit on the changed files - Status: Passed
- [x] Cited paths and facts checked against `develop` - Status: Passed
- [ ] PR CI - GitHub PR checks - Status: Pending

## Flags / Guardrails

None. The guidance is advisory.

## Adjacent Tests Considered

None apply; no code changes.

## Technical Changes

- New `skills/github-ci-pr-quality/SKILL.md` with the TESTING.md
cross-read, five CI change classes, and test-placement, runner-sizing,
trigger-scope, tested-tree, and shared-state rules. Trigger scope
includes checks that path filters match real files and that moves and
deletes update CI in the same PR. It tightens stale-base and approvals,
adds a review checklist, three worked examples, and a completed
retrospective review of #12185 as a model of the required output.
- Review contract: the overlay keeps review read-only (pre-commit runs
in a throwaway checkout), and requires caller edits only for breaking
workflow interface changes.
- New `.github/instructions/github-ci-pr-quality.instructions.md`
(`applyTo: ".github/**"`).
- `AGENTS.md`: the planned catalog row now links to the skill, and the
new instructions file is listed.

## Risk Acceptance / Waivers

`W-DOC`: guidance only; no product or CI behavior changes.

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
dsaffars added a commit that referenced this pull request Oct 23, 2026
JIRA ID: AIHPBLAS-5178

## Summary

- Move the hipBLASLt SolutionUID uniqueness check from the prod 96-core
build runner to a standard GitHub-hosted CPU runner (`ubuntu-24.04`),
with no container.
- Rename the check from `Component CI / hipBLASLt library uniqueness /
Linux` to `Component CI / hipBLASLt library UID uniqueness / Linux`.

## Motivation

`tox -e library-uniqueness` only scans the logic YAML and checks that
every `SolutionUID` is unique. It does not build hipBLASLt, does not use
a GPU, and does not need ROCm. Component CI was still scheduling it on
`aws-linux-scale-rocm-prod` inside the TheRock build container, the same
pool used for rocISA, Geko, and TensileLite coverage. Those 96-core
machines are expensive and in short supply, and the job spent far longer
on checkout than on the test itself.

This is a stopgap for the review feedback on #12185
(#12185 (comment)).
It fixes the runner cost. It does not change where the test lives.

## Technical Details

`.github/workflows/component-ci-library-uniqueness.yml` now runs on
`ubuntu-24.04` with Python 3.12 (using the same `actions/setup-python`
pin as `pre-commit.yml`) and no container. It still runs `python -m tox
-e library-uniqueness`. The workflow no longer takes `docker_image` or
`linux_runner` inputs, and the caller in
`.github/workflows/component-ci.yml` no longer passes them.

The job name is now `hipBLASLt library UID uniqueness`. The nested job
is still `Linux`, so a pull request check is `Component CI / hipBLASLt
library UID uniqueness / Linux (pull_request)`. The only required checks
on `develop` are the summary jobs, so the rename does not affect branch
protection.

The test itself is unchanged. It still uses 8 worker processes
(`HIPBLASLT_UID_TEST_PROCESSES`, default 8) on the runner's 4 vCPUs.

## Test Plan

The workflow file is in the component's trigger list, so this PR
exercises the change on its own CI.

## Test Result

The job passed on the new runner:
https://github.com/ROCm/rocm-libraries/actions/runs/38761106727/job/116512738350.
Total time was about 5 minutes, with about 4 minutes of that in checkout
and about 46 seconds in the gate (including tox environment setup). That
is a little slower in wall-clock time than before, but it is not on the
critical path of Component CI and it no longer uses the prod runner
pool.

## Related

- Follow-up to #12185
(#12185), which introduced
the check.
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.

7 participants