Skip to content

Update README and remove the examples - #398

Merged
demandal25 merged 4 commits into
amd-integrationfrom
amd2-release-validation
Oct 22, 2026
Merged

demandal25 merged 4 commits into
amd-integrationfrom
amd2-release-validation

Conversation

@demandal25

@demandal25 demandal25 commented Oct 22, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

The README now states what was validated at the release head (the full suite on both architectures, in the supported image), what torch.compile does per op, and the one torch.compile known issue left after #397, with its workaround. The ROCm example scripts and tutorial notebook are removed: they duplicated the README's quick start and upstream's documentation, and nothing tested them. The README is also cut from 397 to 292 lines: it keeps quick start, usage, the supported configuration, the full support matrix and what upstream has that this does not, and moves the torch.compile and environment-variable reference into docs/rocm/.

What changed

  • README.md, Supported hardware and toolchain: the paragraph saying gfx942 had only run the prefill, arch-caps and AITER-routing suites is replaced by the full-suite result on both arches, anchored to the v0.6.18+amd.2 tag.
  • docs/rocm/torch-compile.md (new; the README keeps a summary and a one-line warning): adds an append row (append_paged_kv_cache and append_paged_mla_kv_cache compile with the flag on, under fullgraph too except backend="aiter" append), adds the fp8-quantizing norms to the ops the flag cannot register, and replaces "raises a clear error" with a measured per-op table (flag off, flag on, fullgraph=True), a footnote that AITER decode with return_lse=True needs backend="fa2" under fullgraph (Compile AITER decode with return_lse=True under custom ops #388), the host-side flag-on dispatch cost, and what the flag does not cover: plan() stays outside any compiled region, and sampling ops taking a generator, jit_args custom variants and AITER's opt-in norm/RoPE/activation shims are not registered. With the flag off the error is usually torch's RuntimeError when making fake tensor call.
  • docs/rocm/torch-compile.md, Known issue: merges Stop declaring the paged KV cache mutated on read-only attention ops #397's append note into one rule: give every tensor an op writes its own storage, because PyTorch 2.12 can miscompile a write into a view of a larger tensor under every dynamic setting (tables below). That includes append's own single [pages, 2, ...] cache, which the wrapper splits into views, so append users are told to pass two separate caches. Four review rounds each found a layout or mode the previous statement of torch's trigger missed, so the README states the rule rather than the trigger. For reduce-overhead it keeps only Stop declaring the paged KV cache mutated on read-only attention ops #397's measured advice: register the KV cache as a module buffer, since AITER decode copies an argument cache on every replay. The paragraph this branch carried before Stop declaring the paged KV cache mutated on read-only attention ops #397, which scoped the issue to dynamic=True, is dropped.
  • README.md, Basic usage: the pointer to examples/ is now a pointer to upstream's plan()/run() documentation, flagged as tracking upstream's latest release, plus the ROCm list of refused CUDA-only arguments.
  • README.md, the rest (third commit): quick start keeps its commands and links CONTRIBUTING.md for the container gotchas; the two gfx950 routing paragraphs become a pointer to the per-op notes in docs/rocm/backends.md, which already hold them; benchmark caveats are left to benchmarks/rocm/README.md; the env-var table keeps the four variables a user typically sets.
  • docs/rocm/environment.md (new): the full runtime env-var table and the runtime-helper snippet, moved verbatim. CONTRIBUTING.md's link to the README table now points here. The doc-ownership table in .claude/skills/pr-workflow/SKILL.md names both new pages.
  • examples/: removes single_prefill_example.py, batch_prefill_example.py, batch_decode_example.py, amd_flashinfer_rocm_tutorial.ipynb and run_jupyter_server.sh. All five were fork-added (none exists at v0.6.18), so the additive-only rule is untouched; upstream's examples/pytorch/ stays.

Benchmark results

None: documentation and deleted example scripts only, so no kernel or dispatch path changes.

Test plan

Full suite at e1054f3, the release head (this PR is docs and deletions only), in docker/Dockerfile.rocm, one allocated card per arch (bus id checked on gfx950):

gfx942 (MI300X) gfx950 (MI355X)
-n auto --reruns 2 -m "not slow" 33867 passed, 4024 skipped, 0 failed 33875 passed, 4016 skipped, 0 failed¹
-n 1 --reruns 2 -m slow 72 passed 72 passed
Wall time 87 min, warm JIT cache 89 min, cold JIT cache

¹ Four git-dependent tests (test_amd_coverage's two manifest tests, test_redistribution_licences' sdist and wheel exclusions) failed on gfx950 because that copy of the tree had no .git. Both files pass, 125 of 125, in a git checkout of the same commit, and are counted as passed. No other test needed a rerun on either arch.

Flag-on dispatch at afb6440, single prefill qo16/kv128, minimum of 3 interleaved rounds on an idle allocated card:

Flag off Flag on Delta fa2 control delta
gfx942 21.61 µs 42.42 µs +20.8 µs +18.7 µs
gfx950 12.65 µs 23.38 µs +10.7 µs +8.2 µs
  • torch.compile matrix in bf16 at e1054f3 on gfx942 and gfx950, identical cell for cell (fa2 and aiter; single/paged/ragged prefill, decode, MLA, MoE, append, MLA append; flag 0/1; default and fullgraph=True), every compiled result compared to eager: all match. The README table is that result.
  • Writes into views at e1054f3, max |compiled − eager|, identical on gfx942 and gfx950:
Written arguments dynamic=False default dynamic=True
Append into kv[0], kv[1] passed in 4.594 4.594 –
fused_add_rmsnorm(pool[1,0], pool[1,1]) passed in 8.25 8.25 –
Append into one [pages, 2, ...] cache 0 0 5.484
Append into separate K and V 0 0 0

One default-compiled function called at T = 32/48/64/80, once a size goes dynamic:

Written arguments T=32 48 64 80
fused_add_rmsnorm(pool[1,0], pool[1,1]), pool shaped by T 0 12.1 12.4 13
rmsnorm(out=o[1]), o shaped by T 0 8.94 12.5 9.44
Either, on a buffer allocated once at the largest T 0 0 0 0

In-place RoPE on qkv.split views and MLA append on torch.split(buf, [512, 64]) were exact with dynamic=None, False and True on both arches.

  • No remaining reference to the removed files (git grep for the file names, ipynb, jupyter; the matches left are upstream's).
  • No Python or C++ changes, so no tests beyond the suite above apply.
  • /code-review xhigh on origin/amd-integration...HEAD
  • pre-commit run -a

demandal25 and others added 2 commits October 21, 2026 16:53
The three *_example.py scripts called the public API
(single_prefill_with_kv_cache and the batch wrappers' plan()/run()) and
checked each result against an element-wise Python reference: test
drivers, not usage examples. No CI job or pytest path runs them,
tests/rocm/ covers every case they hit, and each release needed hand
fixes to keep them true.

The notebook duplicated the README's setup text and stored outputs that
went stale every release (version string, a PDL warning #382 removed).
Its two walkthroughs with no README equivalent, paged batch prefill and
a LogitsPipe sampling chain, use upstream APIs that upstream's
documentation covers, which the README now links. run_jupyter_server.sh
existed only to serve it. examples/pytorch/ is upstream's and stays.

Co-Authored-By: Claude <noreply@anthropic.com>
…viour

Supported hardware: the paragraph saying gfx942 had run only the prefill,
arch-caps and AITER-routing suites is replaced by the full suite at the
release head e1054f3 in docker/Dockerfile.rocm, one card per arch,
anchored in the README to the v0.6.18+amd.2 tag:

  gfx942  not slow: 33867 passed, 4024 skipped, 0 failed   slow: 72 passed
  gfx950  not slow: 33875 passed, 4016 skipped, 0 failed   slow: 72 passed

On gfx950 four git-dependent tests (test_amd_coverage's two manifest
tests, test_redistribution_licences' sdist/wheel exclusions) failed
because that copy of the tree had no .git; both files pass, 125 of 125,
in a git checkout of the same commit, and are counted as passed.

torch.compile: the section said the flag-off path "raises a clear error".
Measured in bf16 at afb6440 on both arches (fa2 and aiter, flag 0/1,
default and fullgraph; the two matrices are identical row for row) and
re-measured at e1054f3 on both arches with every compiled result
compared to eager (all match), adding append: paged/ragged
prefill and decode run() compile under fullgraph; single prefill and
aiter_fused_moe fetch a cached module inside the traced frame and break
it; MLA compiles with the flag off too and fails fullgraph. #388 then
made AITER decode with return_lse=True compile by breaking the graph, so
fullgraph there needs backend="fa2" (footnote). With the flag off the
error is usually torch's fake-tensor error; FlashInfer's own message
appears only for the guarded fa2 ops under fullgraph. The flag does not
register sampling ops taking a generator or jit_args custom variants
(schema inference rejects them, so they keep the guard), nor AITER's
opt-in norm/RoPE/activation shims. plan() stays outside any compiled
region: the plan ops are deliberately unregistered.

Append rows: append_paged_kv_cache and append_paged_mla_kv_cache fail
with the flag off and compile with it on, under fullgraph too, except
append with backend="aiter", which breaks the graph. The re-measured
matrix is identical on gfx942 and gfx950. The fp8-quantizing norms join
the list of ops the flag cannot register (schema inference rejects
them).

Known issue: #397 stopped the read-only attention ops declaring the KV
cache mutated and added a README note for append, which still does.
Four review rounds each found a view layout or compile mode that the
previous wording of torch's trigger missed, so the README now states
the rule every measurement fits rather than the trigger: give every
tensor an op writes its own storage. Max |compiled - eager| at
e1054f3, identical on gfx942 and gfx950:

                                          dynamic=False  default  True
  append into kv[0], kv[1] passed in      4.594          4.594    -
  fused_add_rmsnorm(pool[1,0], pool[1,1]) 8.25           8.25     -
  append into one [pages, 2, ...] cache   0              0        5.484
  append into separate K and V            0              0        0

Default compile also fails once a size goes dynamic: one compiled
function at T = 32/48/64/80 gave 0/12.1/12.4/13 for fused_add_rmsnorm
on a pool shaped by T and 0/8.94/12.5/9.44 for rmsnorm(out=o[1]). The
single [pages, 2, ...] cache is append's documented layout, split into
K and V views inside the wrapper, so the README tells append users to
pass two separate caches. In-place RoPE on qkv.split views and MLA
append on torch.split views measured exact and are named as the
exceptions: separate ckv/kpe buffers would cost MLA run() a copy of
the page pool on every step, and splitting qkv is how RoPE is called.
The rule says to allocate written tensors up front because a per-call
.clone() satisfies "own storage" while dropping the write. For reduce-overhead the README keeps only what #397
measured on both arches: AITER decode copies a KV cache passed as an
argument into the graph on every replay, and a module buffer avoids
it. Advice to hold the wrapper on the module too was measured harmful
in review (a crash on the second call when the first fa2 run is
captured, and a re-record per plan()), so it is not given.

The paragraph this commit carried before #397, which scoped the issue
to dynamic=True and called default compile unaffected, is dropped.

Flag-on dispatch is host-side, so the README names the test hosts.
Single prefill qo16/kv128, min of 3 interleaved rounds
on an idle allocated card: gfx942 21.61 -> 42.42 us (+20.8; fa2 +18.7),
gfx950 12.65 -> 23.38 us (+10.7; fa2 +8.2).

The usage pointer now names upstream's docs as tracking upstream's latest
release and links docs/rocm/backends.md#cuda-only-arguments, and the
Benchmarking paragraph names the support matrix explicitly.

Co-Authored-By: Claude <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 22, 2026 13:04

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟢 Approval recommended

The documentation matches the supplied validation and implementation evidence, and the example deletions leave no identified dangling references.

No open issues 🎉

What changed in this PR

Prepares the ROCm port’s documentation for v0.6.18+amd.2 by recording the validated configuration and compilation limits, while removing duplicated, untested examples.

Changes:

  • Records full-suite results on gfx942 and gfx950 in the supported development image.
  • Documents measured torch.compile support, dispatch overhead, and remaining workarounds following #397 and #388.
  • Replaces ROCm example links with upstream API documentation and ROCm-specific restrictions, then removes five fork-added example files.
File Description
README.md Updates release validation, compilation guidance, and API documentation links.
examples/​single_prefill_example.py Removes the standalone single-prefill example.
examples/​run_jupyter_server.sh Removes the tutorial’s Jupyter launcher.
examples/​batch_prefill_example.py Removes the paged and ragged prefill examples.
examples/​batch_decode_example.py Removes the standalone batch-decode example.
examples/​amd_flashinfer_rocm_tutorial.ipynb Removes the duplicated ROCm tutorial notebook.

Review effort: Balanced

@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Security scan found no critical or high findings on lines changed by this pull request

View the security scan run for complete reports.

“New” means the finding is located in a changed file on an added or modified line; it is not a base-versus-head findings delta.

The README had grown to 397 lines, two-thirds of it reference for a
reader already debugging rather than one getting started. It keeps
what a developer needs first: quick start, usage, the supported
configuration, the full support matrix and the list of what upstream
has that this does not. It drops to 292 lines.

Moved verbatim to new pages:

  docs/rocm/torch-compile.md   per-op compile table, footnotes,
                               unregistered ops, the full known issue
  docs/rocm/environment.md     all 19 runtime variables and the
                               runtime-helper snippet

The README keeps a summary of each: how to enable torch.compile, to call
plan() outside the compiled region, and the known issue in the form a
user acts on (separate K and V caches for append, a whole tensor for
out=); and the four variables a user typically sets, in environment.md's
wording so the two do not drift. The container gotchas and the
torch-version detail are already in CONTRIBUTING.md and are linked
rather than repeated; the two gfx950 routing paragraphs are already in
the per-op notes of docs/rocm/backends.md and become a pointer ahead of
the upstream-gaps subsection. Quick start keeps the base image name
(pyproject.toml points readers there for it), the note that AITER decode
builds at plan() and MoE on first use, and the jit-cache wheel's scope.
The pr-workflow skill's doc-ownership table names the two new pages.
CONTRIBUTING.md's link to the README's env-var table now points at
environment.md. README links stay absolute because pyproject.toml uses
it as the package description; the new pages link relatively. Quick
start also states the image build time (~35 min), that the image carries
no source, that outside the image amd-aiter must be source-built at its
tag or every AITER route silently runs on fa2, and that the jit-cache
wheel is built, not published. The supported-configuration section says
the suite needs a git checkout (four tests read the git index) and keeps
the sentence the CPU-only-torch error in hip_utils.py points readers to.
The routing pointer names all four per-arch differences.

Co-Authored-By: Claude <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 22, 2026 14:43

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

The installation guidance incorrectly promises fallback without AITER for APIs that require it.

1 open issue

Review effort: Balanced

Comment thread README.md Resolved
The quick start said every AITER route silently runs on fa2 without
amd-aiter. Only auto prefill and decode do: MLA (_require_aiter_mla),
aiter_fused_moe and the opt-in norm, RoPE and append shims call
require_aiter, and an explicit backend="aiter" request raises, so a
reader skipping the AITER build would find those unusable rather
than slower.

Co-Authored-By: Claude <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 22, 2026 15:00
@demandal25 demandal25 changed the title State the validated configuration for v0.6.18+amd.2 and remove the ROCm examples Update README and remove the ROCm examples Oct 22, 2026
@demandal25 demandal25 changed the title Update README and remove the ROCm examples Update README and remove the examples Oct 22, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟢 Approval recommended

No unresolved blockers remain in these documentation updates and example removals, and the prior AITER fallback concern is addressed.

No open issues 🎉

1 resolved since last review

Review effort: Balanced

@demandal25
demandal25 merged commit 5f2e2b2 into amd-integration Oct 22, 2026
14 checks passed
@demandal25
demandal25 deleted the amd2-release-validation branch October 22, 2026 15:11
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.

2 participants