Skip to content

Refactor: make the examples tree internally consistent - #1547

Merged
ChaoWao merged 1 commit into
hw-native-sys:mainfrom
ChaoWao:refactor/examples-consistency
Jul 28, 2026
Merged

Refactor: make the examples tree internally consistent#1547
ChaoWao merged 1 commit into
hw-native-sys:mainfrom
ChaoWao:refactor/examples-consistency

Conversation

@ChaoWao

@ChaoWao ChaoWao commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

Why this instead of writing 27 READMEs

The ask was READMEs for the 27 example directories that lack one. Measuring the tree first changed the answer: documenting it as-is would have written the inconsistencies down rather than removed them, and would have copied the duplication into the docs. This is the cleanup that should come first. No behaviour changes.

What this fixes

Test module names did not match their directory. paged_attention_manual_scope and paged_attention_unroll_manual_scope, on both arches, each carried the plain paged_attention test name — so a failure report named a directory that was not the one running. Renamed to match.

scalar_data_testscalar_data: the directory suffix only duplicated what test_ already says. The file inside keeps its name and now matches.

vector_add keeps two test modules on purpose — test_run_timing.py asserts the [STRACE] markers. That is a second test, not a mismatch, so it is left alone.

Four L3 examples had no __init__.py while every sibling did (allreduce, ffn_tp_parallel, l3_l2_message_queue, l3_l2_orch_comm_stream). Every one of these tests does from .main import run, so without the marker that relative import leans on rootdir inference instead of being a package.

allreduce had no test at all — the only L3 example without regression protection, and it is a collective. It now has one. I checked first whether it merely duplicated tests/st/worker/collectives/allreduce: it does not. That one holds four algorithm variants; this one has its own main.py demo and no test. It was an oversight.

A Stride normalization was dropped from this PR after review

An earlier revision of this branch also rewrote bare Stride< to pto::Stride< across 24 a2a3 kernel files, on the reasoning that the qualified spelling was "the portable one".

That was wrong, and it is reverted. The kernels carry using namespace pto;, and there is exactly one Stride in the pto headers — no ambiguity — so the qualification is redundant. Worse, Shape lives in the same namespace and stayed bare, so the change produced adjacent lines like:

using DynShapeDim5 = Shape<1, 1, 1, vRows, vCols>;
using DynStridDim5 = pto::Stride<1, 1, 1, kTCols_, 1>;   // inconsistent

Making it genuinely consistent would mean qualifying every Shape too — 50 more files, purely stylistic, and not something to bundle into a consistency PR unasked. The .cpp files are byte-identical to main again; the only .cpp changes remaining are the three that moved with the scalar_data rename, verified by checksum.

What measuring the tree exposed, and did not fix

Deliberately not in this PR:

Paired example Lines Differing What differs
vector_example 454 4 3 × Stride spelling, 1 × platforms
deferred_notify_demo 386 8 platform strings only
async_notify_demo 409 15 platform strings only
sdma_async_completion_demo 393 35 mostly platform strings
paged_attention ×3 variants 1130–1355 166–292 the above plus real tile geometry (16/32/64/128)

Roughly 5,280 lines of near-duplicate example code, and tests/st/ has the same shape — 18 same-named directory pairs. Merging is technically feasible: arch comes from the platform string, not the path (KernelCompiler(platform=…)), and CASES[*].platforms exists precisely to declare several at once.

Not proposed here for two reasons. It changes the arch-first directory convention, and it runs counter to in-flight work — #1450 is porting a2a3 tests to a5 by copying, adding 29 more files of exactly this duplication. That is a maintainer's call about direction.

READMEs are best written after that decision: merging the four trivially-duplicated pairs would cut the number needed roughly in half.

Verification

  • ruff check / ruff format --check clean across examples/
  • git records all 8 moves as renames, so history is preserved
  • No .cpp content changes remain — confirmed by diffing every examples/**/*.cpp against main and by checksumming the three files that moved with the rename
  • New test's syntax, relative import and marker set verified to match its multi_chip_dispatch sibling exactly
  • Local pytest collection is blocked by a stale _task_interface in my venv — the repo's own build-stamp guard rejects it. Confirmed environmental, not introduced here: the pre-existing multi_chip_dispatch test fails collection identically. CI is the real check.

allreduce's test is scoped to a2a3sim/a2a3 rather than all four platforms: that is what the demo's own README and CLI default document. The algorithm runs on a5 (tests/st/worker/collectives/allreduce declares all four), so widening is likely fine — but nobody has run this demo there, and I could not verify locally, so I did not assert it.

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@ChaoWao, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 57 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 0531b373-1c35-45de-8c53-c8dadb016e0e

📥 Commits

Reviewing files that changed from the base of the PR and between 40b6329 and dc5bf02.

📒 Files selected for processing (13)
  • examples/a2a3/tensormap_and_ringbuffer/paged_attention_manual_scope/test_paged_attention_manual_scope.py
  • examples/a2a3/tensormap_and_ringbuffer/paged_attention_unroll_manual_scope/test_paged_attention_unroll_manual_scope.py
  • examples/a2a3/tensormap_and_ringbuffer/scalar_data/kernels/aiv/kernel_add.cpp
  • examples/a2a3/tensormap_and_ringbuffer/scalar_data/kernels/aiv/kernel_noop.cpp
  • examples/a2a3/tensormap_and_ringbuffer/scalar_data/kernels/orchestration/scalar_data_orch.cpp
  • examples/a2a3/tensormap_and_ringbuffer/scalar_data/test_scalar_data.py
  • examples/a5/tensormap_and_ringbuffer/paged_attention_manual_scope/test_paged_attention_manual_scope.py
  • examples/a5/tensormap_and_ringbuffer/paged_attention_unroll_manual_scope/test_paged_attention_unroll_manual_scope.py
  • examples/workers/l3/allreduce/__init__.py
  • examples/workers/l3/allreduce/test_allreduce.py
  • examples/workers/l3/ffn_tp_parallel/__init__.py
  • examples/workers/l3/l3_l2_message_queue/__init__.py
  • examples/workers/l3/l3_l2_orch_comm_stream/__init__.py

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@ChaoWao
ChaoWao force-pushed the refactor/examples-consistency branch 2 times, most recently from 3159fe9 to dc5bf02 Compare July 28, 2026 08:43
Three inconsistencies, each of which makes the tree harder to read than
the code in it warrants. None changes behaviour.

Test module names now match their directory. Four scene tests were named
after a sibling example rather than their own:
paged_attention_manual_scope and paged_attention_unroll_manual_scope, on
both arches, each carried the plain paged_attention test name, so a
failure report named a directory that was not the one running.
scalar_data_test is renamed to scalar_data, since the directory suffix
only duplicated what test_ already says; the file inside keeps its name
and now matches. vector_add keeps two test modules on purpose:
test_run_timing.py asserts the [STRACE] markers and is a second test,
not a mismatched one.

Four L3 example directories gained the __init__.py their siblings all
have. Without it the package-relative `from .main import run` that every
one of these tests uses depends on rootdir inference rather than being a
package.

allreduce had no test at all, so the only L3 example without regression
protection was a collective. It now has one, scoped to a2a3: the demo's
own README and CLI default document that platform, and while the
algorithm is covered on a5 by tests/st/worker/collectives/allreduce,
nobody has run this demo there. Widening it is a separate, verifiable
step. The test documents that run() takes (device_ids, platform), the
reverse of the single-device demos beside it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ChaoWao
ChaoWao merged commit 108cfd6 into hw-native-sys:main Jul 28, 2026
18 checks passed
@ChaoWao
ChaoWao deleted the refactor/examples-consistency branch July 28, 2026 09:13
ChaoWao added a commit that referenced this pull request Jul 28, 2026
Kernel sources carry two conventions. The collectives kernels qualify
(pto::Stride<...>) and use no using-directive; the older scene-test
kernels open with `using namespace pto;` and use bare names. Each is
internally consistent, and nothing recorded which one new code should
follow, so the split propagates by whichever file an author copied from.

Rule 11 names qualification as the direction, because it is the only
spelling that compiles whether or not a using-directive is in scope, and
because a file-scope `using namespace` is what most style guides steer
away from. New kernels qualify and do not add the directive; existing
bare files are not defects and need no churn.

The load-bearing part is the constraint that a file is qualified
completely or not at all. Shape, Stride, Tile and GlobalTensor all live
in namespace pto, so qualifying one and leaving its siblings bare yields
adjacent lines that read worse than either consistent state. That is a
real failure mode rather than a hypothetical: an earlier revision of
PR #1547 rewrote Stride across 24 files and left Shape alone, and the
resulting mixture is why it was reverted.

A repo-wide sweep is ruled out with the measurement that rules it out:
the 142 files carrying the directive hold roughly 3,200 bare uses, of
which Tile alone is 2080. Rewriting them would touch every kernel,
collide with every in-flight branch, and risk regex damage for no
functional gain. Unifying the tree in one go needs its own decision plus
a lint rule to hold the line.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant