Repository navigation
Conversation
The later changes grow several files past the lean rule's 600 lines. This commit only moves code: affine.zig's kernel loading into affine_load.zig and its stream launcher into affine_stream.zig, the relu^2 stream tile records into hip_records_relu2.zig, the Flash Next lane round into lanes_round.zig, the sparse attention loop into mixers_attend.zig, the sparse attention launcher into flashnext_sparse.zig, and decode.hip's expert pick into decode/select.hpp. Exactness: same bytes (no code changes). Tests: none new; the existing tests cover the moved code.
Five records of the 1-row, 2-column stream tiles no longer matched what hipcc compiles for them. They take the usage that tf-hip-kernel-contract limits reads from the code objects. Exactness: same bytes (records only). Tests: the existing gate-5 limits check.
tf-flashnext-hip-test generate prints the two best tokens of the first N steps and the gap between their logits, read from the row's bytes. A near-tie shows as a small gap, which tells a real divergence from a tie. Exactness: same bytes (test tool only). Tests: none (a diagnostic option of the test tool).
The n-gram row tables were read from the checkpoint mapping, so a round's gather could fault pages in. A single rank now copies them into anonymous memory at load and drops the page cache's copy. policy rows=mapped keeps the mapping; ranks of a group keep it too, as they share the page cache. Exactness: same bytes (the same rows from another place in memory). Tests: policy words test with rows=mapped.
|
Hi @davidtai, a heads-up that #1694 overlaps with the stream-tile part of this series. It is the stream-tile work I mentioned in question 4 of #1563. Both change
Two things from my side that may help when you split the series:
On Qwen3.8-27B it gives +30% aggregate at 8 streams and +47% at 16, with the bytes unchanged. I'm happy to rebase onto your series, or for yours to build on this one, whichever the maintainers prefer. |
Flash Next on HIP cuts prompts at 4,096 rows unless --policy or TF_POLICY names prefill_step. Each expert's rows of a chunk are one launch, and the prompt scratch stays small. prefill_step=20480 runs a 20K prompt in one pass: on a 192 GiB gfx1151 machine, about 3 % faster 16K prefill for about 24 GiB more GPU memory. The Flash Next recipe states it as an opt-in. Policy.names tells whether the flags or TF_POLICY name a key, so a family default never overrides one. Exactness: same bytes (a prompt's rows and sums do not depend on the chunk). Tests: Policy.names in the flags and in TF_POLICY, and only as a key.
tf_router_select computes a decode or verify window's router logits from the bf16 rows, and its last block picks the top-k and writes tf_moe_route's plan, for 1 to 8 rows. It stages up to 2 rows of x in dynamic shared memory and picks a row a wave (half a wave a row at 5 to 8 rows). A row with a NaN logit takes the rank-loop pick, so its bytes are select_body's. Shapes it cannot take keep the two launches. Exactness: same bytes (bf16 rows widened exactly; the same pick and plan). Tests: decode_route.zig, the one-launch router and pick against the two launches (513 x 2560, top 10) and against served plans' picks and items byte for byte (served_plans.bin, rows 1 to 8). Contract records: tf_router_decode_f16/bf16, tf_router_select_f16/bf16.
tf_topk read a whole row in one block. tf_topk_part takes each part's top k over the card, and tf_topk_join takes each row's k from the parts' candidates in tf_topk's order. The row's top k are among its parts', so the ids, values and order are tf_topk's. Exactness: same bytes. Tests: ops_flashnext.zig, top-k in parts against tf_topk byte for byte (Flash Next draft and full vocabularies). Contract records: tf_topk_part, tf_topk_join. Contract tests: contract_topk.zig (bit-equal to tf_topk, and tf_topk's key order).
The 1-row stream tile loads a round's x chunk before it fetches the next round's codes, so the dots wait for this round's loads only. Exactness: same bytes (the same sums in the same order). Tests: the existing stream tile tests. Contract records: the stream tile records re-derived from the code objects.
A wave's column sums run in one transposing butterfly (DPP row_xmask and permlanex16, ported from Strata's tsum, MIT, notice in THIRD_PARTY_NOTICES.md). Each sum is bitwise the xor butterfly's it replaces. Exactness: same bytes. Tests: the existing stream tile tests. Contract records: the stream tile records re-derived from the code objects.
The plain stream tile also compiles one column a lane, which a narrow launch takes to fill the card with waves. A SwiGLU pair needs two columns and relu^2 keeps its tiles. The relu^2 pair test reads the launcher's stream constants instead of a copy. Exactness: same bytes (a column's sum does not depend on the columns beside it). Tests: the relu^2 pair contract test on the launcher's constants. Contract records: the 1-column plain tiles at every width and row count.
Past the tile's rows, a launch puts its row blocks on the grid's x and its column blocks on y, so a column block's row blocks run together and read its codes once from cache. Exactness: same bytes (block order only). Tests: the existing stream tile tests.
A SwiGLU pair lane takes at most 8 code words (2 columns at 4 bits), which keeps more waves in flight. Kernels.stream_cb_force lets a test force the columns a lane. Exactness: same bytes (a column's sum does not depend on the columns a lane). Tests: decode_products.zig, the routed gate+up and down at every columns a lane and as single-pair items (Flash Next, 1 to 8 rows), byte for byte.
A routed plain product (the experts' down) takes at most 4 columns a lane at the 2- and 4-row tiles. Exactness: same bytes. Tests: covered by the routed byte test of the SwiGLU pair change.
One row of an unrouted plain product under 20,000 columns takes one column a lane; wider heads keep the waves rule. Exactness: same bytes. Tests: decode_products.zig, a plain product at every columns a lane (in-proj K, out-proj, a ragged N; 1 to 4 rows), byte for byte.
A 2- or 4-row pass with one live row loads and dots that row only. A row's sums do not depend on the rows beside it, so the bytes are the same. Exactness: same bytes. Tests: covered by the routed byte test (single-pair items run every pass on one row). Contract records: the stream tile records re-derived from the code objects.
A routed 4-bit plan of 5 to 8 rows runs as a work list in its own kernel (stream_list): grid z blocks walk the items, so no block starts for a dead item or a dead row block. A row's sums are those of the grid launch. Exactness: same bytes. Tests: covered by the routed byte test (the engine's launch at a.m = the window's rows). Contract records: the 4-bit SwiGLU and plain work lists.
Plain 4-bit products of 3 and 4 rows take a held-codes body that makes a round's code pairs once and dots every row's x with them; 5 to 8 rows run in one 8-row pass by width. The sums are affine_dot2_stream's. Exactness: same bytes. Tests: heldPick's picks by rows and width. Contract records: the held tiles 4x1, 4x2, 4x4, 8x2, 8x4.
Flash Next's prompt expert gate+up (with SwiGLU as the epilogue) and down run on one shape-parameterized gfx11 matrix-core tile (tiles/moe_gemm.hpp) with affine_wmma_gemm's arithmetic. Its loads stay in flight across the window barriers (lds_barrier). A prompt plan's launches cover its live items only. Records of tiles only gfx11 launches carry no usage on the other chips (HipLaunch.served). Exactness: same bytes (the matrix tile's sums and moe_act's rounding). Tests: decode_products.zig, prompt gate+up and down against the matrix tile and moe_act byte for byte; decode_route.zig, a prompt plan's live items before planItems; moe.zig's planItems bound; the served check. Contract records: affine_wmma_moe_gu, affine_wmma_moe_down (gfx11 only).
A prompt's plain 4-bit group-32 products at Flash Next's K (320, 2560, 6144, 10240) run on a K-specialized gfx11 matrix-core tile (tiles/dense_gemm.hpp, block layout after Strata's gfx11 kernels). It writes bf16 where the prompt cast its fp32, with the cast's rounding. hc up runs with the HC mix as its epilogue and reads its gates from a table of rnd(sigmoid(g)) for every bf16 g, filled once a device. Exactness: same bytes (the matrix tile's sums, tf_cast's rounding, tf_fn_hc_mix's mix). Tests: decode_products.zig, dense products against the matrix tile and the cast; flashnext_hc.zig, hc up with the mix in the epilogue against the product then tf_fn_hc_mix; the registry's pick of the dense tile. Contract records: affine_wmma_dense at each K, tf_affine_dense_hcmix, tf_hc_gate_fill (gfx11 only). Contract tests: contract_wmma_dense.zig, contract_hc_mix.zig (the hcmix tile and the gate table), and contract_wmma_moe.zig for the previous change's expert tiles (it reads this change's dense upload).
A prompt's DeltaNet rows (Dk = Dv = 128, 64 rows or more) run at half a value head a block, 4 lanes a row, in the same sum order as the wave-a-row kernel. Exactness: same bytes. Tests: gdn.zig, the half-head kernel against a wave a row, bit for bit (Flash Next: 16 key, 48 value heads). Contract records: tf_gdn_prompt_128. Contract tests: contract_gdn.zig (y and state, bit-equal to gated_delta_tile).
tf_gdn_prompt_prep runs a DeltaNet layer's prompt conv, split, q and k RMS norms, v, new conv state, gate and beta in one launch, with the values of the launch chain it replaces. Exactness: same bytes. Tests: chain.zig, the merged launch against the chain's q, k, v, gate, beta and conv state. Contract records: tf_gdn_prompt_prep. Contract tests: contract_gdn_prep.zig (bit-equal to the chain it replaces).
A window of more than one row no longer writes a DeltaNet state snapshot per row. It holds the state, keeps its k, v, gate and beta, and the keep runs every layer's state through the kept rows in one launch (tf_gdn_keep). A keep that drops rows names the conv-tail snapshot row the next window starts from. Snapshots, restores and the worker settle the conv tails first, and reset writes the window start word. Exactness: same bytes (the same recurrence over the same rows). Tests: gdn.zig, a held window and its keep against the stored window, and a window started from a snapshot row; state_test.zig, save and restore with a named row, and a cancelled stream's slot leased again fresh. Contract records: tf_gdn_hold_128, tf_gdn_hold_16, tf_gdn_keep_128, tf_gdn_keep_16. Contract tests: contract_gdn_hold.zig (hold and keep at 128 and 16, bit-equal to gated_delta_tile).
At 16 rows or more of Flash Next's 4 x 128 index heads, tf_fn_idx_scores_quad scores a block at 4 lanes a score, in tf_fn_idx_scores's sum order. Exactness: same bytes. Tests: flashnext_attn.zig, the 4-lane scores against a wave a block, bit for bit. Contract records: tf_fn_idx_scores_quad. Contract tests: contract_fn_scores.zig, the quad form (bit-equal to tf_fn_idx_scores).
tf_fn_qsa_prep runs a sparse layer's q, index q and k norms and rotations, the v and raw index key cache writes and the completed blocks' pools in one launch at decode and verify rows. The decode chain also finds select's cut bin by the block and scores a window's 5 to 15 rows 8 rows a wave. Exactness: same bytes. Tests: flashnext_attn_tiles.zig, the prep launch against the seven launches it replaces (1 to 4 rows); flashnext_attn.zig, the 8-row scores against one row at a time; prepWrites' cases. Contract records: tf_fn_qsa_prep, tf_fn_idx_scores8. Contract tests: contract_fn_qsa.zig (bit-equal to the seven launches); contract_fn_scores.zig, the window form (bit-equal to tf_fn_idx_scores).
A window's and a prompt's MoE combine run inside the next hyper-connection norm, one launch for both. The bf16 HC norm and mix use 16-byte accesses. Exactness: same bytes (moe_combine_kernel's then tf_fn_hc_norm's). Tests: flashnext_hc.zig, the combine in the norm (1 to 8 rows, and a prompt's rows) and the 16-byte norm and mix against the per-element kernels, byte for byte. Contract records: tf_fn_hc_mix8, tf_fn_hc_norm_v, tf_fn_hc_norm_moe, tf_fn_hc_norm_moe_v. Contract tests: contract_hc_mix8.zig and contract_hc_norm.zig (bit-equal to the per-element kernels).
A prompt's expert picks run a wave a row (tf_select_rows, select_body's bytes), and its plan runs in three launches over 512-pair segments (count, scan, scatter) with tf_moe_route's members and items. The prompt router tile takes 128 x 64 blocks. Exactness: same bytes (the router tile keeps every logit's fp32 fma chain). Tests: decode_route.zig, the wave-a-row picks against select_body; ops.zig, the three-launch route; ops_flashnext.zig, the router tile against the host's fma chain. Contract records: tf_route_count, tf_route_scan, tf_route_scatter, tf_select_rows. Contract tests: contract_route.zig (bit-equal to tf_moe_route, and the stated plan); contract_select.zig for tf_select_rows and the router change's tf_router_select_f16 and _bf16 (it uses the route test's plan check): bit-equal to upstream, the stated pick rule, and upstream select_body's NaN and short-row ranks as a known finding at gate 1.
A stream that cannot draft (--no-drafts, "draft": false or --mtp-drafts 0) gets no MTP head caches and no head prompt pass. The head's prompt pass runs on the prefill tiles and writes its caches only. Exactness: same bytes (drafted output equals plain output; the caches hold the same keys). Tests: state_test.zig, a state saved without the head refuses a drafting stream and resumes one without.
A sampled stream's draft is the target's keyed Gumbel-max over the head's top-k survivors, so the draft agrees with the target whenever the head ranks the target's winner the same. The head's argmax probability is computed only where the confidence gate reads it. Exactness: same bytes (the target never reads the draft; a verify keeps the target's draws). Tests: none new (the lane verify tests cover the draws).
One rank times one stream's window forwards and a head step at load, and the depth rule prices each depth from them; plain rounds compete with drafted ones once the forwards are timed. Exactness: same bytes (only the draft depth changes; drafted output equals plain output). Tests: draft_sources_hip_test.zig sets the new costs field.
A Flash Next verify window holds up to 7 drafts past its pending token (--mtp-drafts up to 7); the other HIP families keep 3. Every rank refuses more than the widest family cap before the load. Exactness: same bytes (drafted output equals plain output). Tests: native/hip.zig, the draft caps per family and the refusal past 7.
--policy mtp_depth=gated drafts to the cap every round and the head's confidence (--mtp-confidence) ends the chain; core/lanes pins the depth (Model.pinned_depth). Flash Next's HIP default is a chain gated to 7 drafts under 0.9 where no flag or mtp_depth key names one. The rule's sampled-stream behaviour under a confidence floor is unchanged. Exactness: same bytes (drafted output equals plain output). Tests: depth.zig, a pinned depth drafts the most; native/hip.zig, Flash Next's own policy and the others' default.
Ops carries a second stream and a ring of events: fork makes later side work start after the stream's work so far, join the reverse. A slot is recorded and waited on in one call, so the ring may wrap between joins. Exactness: same bytes (nothing runs on the side stream yet). Tests: side.zig, more forks than the ring before one join (515 forks).
At one-row decode, tf_moe_prefetch reads the live items' experts' down codes into the caches on the side stream while the gate and up run; an asm register sink keeps the loads. It writes nothing; the forward joins the side stream after its last layer. Exactness: same bytes (the kernel only reads). Tests: none new (the decode tests run with it). Contract records: tf_moe_prefetch. Contract tests: contract_prefetch.zig (gates 1 to 3: every buffer and guard stays as prepared).
|
Hi @davidtai, a follow-up on the GatedDeltaNet scan. I had a rework of
Yours is faster on every prompt it takes, and my rework doesn't move decode measurably, so I won't open a competing PR. Two parts of it may still help you:
I can send either one as a PR on top of your split, or you can take them, whichever suits you. |
Exactness, performance and memory of the series tip against main 94b90c9 on an AMD Strix Halo (gfx1151) machine with 192 GiB of unified memory, both arms alternating in each round, and the contract, test and hash results. The README states what each folder holds. Logs are sanitized copies: local paths, host and user names are placeholders; values are unchanged.
a39a232 to
2f42c9c
Compare
Refs #1661.
Draft. This pull request is a series of 34 self-contained commits, one change each, on
main94b90c9db.Each commit has its own tests, its kernel-contract registration (gates 1-4 test type and gate-5 record) and its
exactness statement. We can split the series into separate pull requests in any grouping the maintainers prefer.
Scope
The gfx11 HIP path for Qwen3.8-Flash-Next, measured on gfx1151. Every commit keeps the output bytes of the base path:
the greedy logits hash is
243ecea88fe50d9fatmainand after each of the 33 code commits.The rounding-class kernels and the
numerics=exact|inexactswitch of the earlier squashed head are not in this pullrequest. #1661 records why (FP64 error and row-grouping dependence) and keeps their results, labelled.
Commits
4ee2e85bef7ac354c588aa18df99411438ecdaf7ec74f12a6370ed4115368ffeb50c0b43bff7fc1a8c0a9e6270fd4797d56461d8e001fc3d43bc7e432e36fc61088491a7821dc4c49bcd8a63b72f868fa8adb89effe42ccbbbfc1b6c016979701c7ca4dd7dbafaee2750fb5c2a126091861529bc14f132d54aec99b0d0bd8d9e3346a4ee89c6cb6e4727c66d5a1fc78137aed1a032f42c9cb6Groups: 1-3 preparation (file moves without change, refreshed records, a test-tool flag); 4-5 load and prompt policy;
6-17 decode kernels; 18-26 prompt kernels; 27-33 lossless speculation and the side stream; 34 the receipts.
Results: this series against
mainPrefill, decode and memory charts
Machine: an AMD Strix Halo (gfx1151) machine with 192 GiB of unified memory, ROCm 7.15.
Checkpoint:
TensorFold/Qwen3.8-Flash-Next-MLX-4bit-MTP, revision2b170fa6. Greedy. Prompt cache off.Tested: the tip of this series (
37aed1a03) againstmainat94b90c9db, the commit it is based on.The two arms alternate in each round. Both builds give the same output tokens.
One 16,384-token prompt of public source code, 1,024 output tokens, 6 runs a row, median:
--no-drafts)main--no-drafts)mainCold prefill (
max_tokens1, a fresh server a run, 2 runs, median):main, tok/smain, GPU / RSS (GiB)Four concurrent streams (
tools/bench_concurrent.py --levels 1,4 --alone --serial), aggregate decode: 117.4 against89.65 tok/s (code), 99.75 against 72.95 tok/s (chat). Concurrent equals alone and drafted equals plain for both builds.
Definitions: prefill tok/s = prompt tokens / TTFT. Decode tok/s = (output tokens - 1) / (last token time - first token
time). Spec-decode hit rate = accepted drafts / drafted, over every drafted request of the row (16, 256 and 1,024
tokens). GPU = peak GTT + VRAM in use less the idle machine's. RSS = the server's peak resident memory. The two come
from the same unified memory and overlap, so do not add them.
Why the hit rate is lower and decode is faster
The two builds draft differently. The server logs show it (1,024-token requests; the counters are identical on all
6 runs of each build; time a round = the median decode window over 6 runs / rounds):
mtp drafts 7 under 0.9,mtp_depth=gatedmainmtp drafts 3 under 0.3Commit 31 lets the chain go to 7 drafts and ends it after the first draft with a head confidence under 0.9.
The longer chain drafts more tokens that the target rejects (396 against 247), so accepted / drafted falls.
But a round now gives 2.55 tokens in place of 1.96 and costs only 2 % more time: commit 30 verifies up to 8 rows in
one window, and commits 6-17 make each row cheaper. So the series needs 23 % fewer rounds for the same 1,024 tokens. Serial decode is also
faster: 28.0 ms against 33.3 ms a token.
Memory, and the settings that change it
The memory A/B ran one fresh server a setting at
--context 20480, 2 rounds, each with one cold 16,384-token prefill.The load lines are identical in both rounds, and GPU and RSS differ by at most 1.7 GiB; the table shows round 1.
Load line = the server's own
GiB on the deviceline.--policy prefill_step=20480--policy prefill_step=1024--policy rows=mapped, rows not in the page cache--policy rows=mapped, rows in the page cache--policy prefill_step=1024,rows=mappedmainTwo commits change memory, one for each counter:
a 4,096-row default prompt chunk): the prompt scratch grows with the chunk. The defaultholds 4.2 GiB more than
main(82.73 against 78.50 GiB) and prefills 51 % faster at 16K. At 1,024 rows the seriesholds 0.23 GiB less than
main.prefill_step=20480is the opt-in for machines with that memory free:+3.5 % prefill at 16K (551.8 against 533.1 tok/s) for +23.8 GiB. The Flash Next recipe documents it.
n-gram tables as a resident copy at load): the checkpoint's n-gram tables are 29.80 GiB. The seriescopies them into anonymous memory at load, so RSS stays near 104 GiB at every prompt length.
mainreads them fromthe file mapping, so its RSS grows as prompts touch more rows (76.8 GiB at 2K, 86.7 GiB at 262K).
rows=mappedkeeps the mapping: RSS 78.6 GiB. With the rows in the page cache it costs 0.6 % prefill at 16K.When they are not (the copy at load dropped them from the page cache), the first prompt reads them from disk and
prefill falls to 353.9 tok/s. The GPU counter does not include the copy.
The two counters overlap on unified memory: the uploaded weights are in both. With its defaults the series holds
82.7 GiB of GPU memory plus the 29.8 GiB copy in anonymous memory.
mainholds 78.5 GiB plus the rows it has touchedin the page cache, which the kernel can drop under memory pressure.
--policy prefill_step=1024,rows=mappedbringsboth counters to within 0.25 GiB of
main's.RAM class: every number in this pull request comes from one machine with 192 GiB of unified memory (184.6 GiB reported
by the kernel). We did not measure a smaller machine, and a budget on this one is not a measurement on a smaller one.
Exactness
On the tip of the code commits,
37aed1a03, with the upstream scripts, server--context 32768 --parallel 4 --prompt-cache-gib 1 --no-thinking:zig/tests/qwen35/serve_check.py(drafted == plain, greedy and sampled; solo == together; a long prompt among decoders; resumed == fresh)draftignored)zig/tests/qwen35/serve_cancel.pyzig/tests/flashnext_hip/rewind.py, prompt cache on against off (turns, regenerate, edit, delete)generate --hashon a 10,368-token prompt at--chunk512, 2,048, 8,192 and 20,480c8f6888043c972e0The Flash Next greedy hash (
generate --chat --max 64 --hash) is243ecea88fe50d9fonmainand on the tip.Kernel contract
On the tip of the code commits,
37aed1a03, gfx1151, zig 0.17.0, ROCm 7.15:zig build test -Dhip=true,zig build hip-kernel-test,zig build test-cuda-hostandzig build native-hip tf-flashnext-hip-test(gfx1151, ReleaseFast) exit 0 on the same tip. Each new or changed kernel is registered: a gates 1-4 test type inzig/tests/hip/contract_*.zigand a gate-5 record inzig/src/core/contract/hip_records*.zig. A kernel that replacesanother names it, so gate 3 requires its bytes to equal the replaced kernel's.
Known findings that the new kernels carry (each spec declares it; bytes stay equal to the kernel they replace):
tf_select_rowsandtf_router_select_bf16keepselect_body(the MoE pick onmain): a NaN shares rank 0with the top number, so slot 0 races, and a row with fewer than k numbers leaves pick slots unwritten.
tf_fn_idx_scores_quadandtf_fn_idx_scores8keeptf_fn_idx_scores's relu,fmaxf(x, 0): a NaN head dotscores 0 where float64 keeps the NaN.
Per-commit checks
Each of the 33 code commits, built and tested alone on an earlier
main(abf822585), with zig 0.17.0:zig build native-hip tf-flashnext-hip-test(gfx1151, ReleaseFast),zig build test -Dhip=true,zig build hip-kernel-testandtf-flashnext-hip-test generate --chat --max 64 --hash. All exit 0.The hash is
243ecea88fe50d9fafter every commit (checks/per-commit.tsvin the receipts).Zig prints a passing test's stderr under a
failed command:line; the exit code is 0.The added and removed lines of each tested commit equal those of the commit here, with two exceptions:
commits 19-33 ran before their gate-5 records were refreshed (
zig/src/core/contract/hip_records_*.zigonly), andcommit 5 ran with a 20,480-row default chunk, which this pull request sets to 4,096 rows.
tools/zig/lean_check.py: 424 problems onmainand 424 on the tip (zero added).The receipts folder (commit 34,
docs/receipts/gfx1151-flashnext-hip-37aed1a0/) has the logs, the request andreply records, the memory samples, the environment and the provenance, with SHA256SUMS.
Not run
core/lanesis shared.test-cuda-hostran.Overlap with open work
atc overlapandgit merge-treeagainst the open pull requests that share files with this series.Conflicts that this series adds:
maintoday: hip: an opt-in prompt GEMM tile that stages dequantized bf16 weights (dq=on) #1650, hip: a 64-row routed prompt tile for many-expert plans on gfx1151 #1658, hip: load a shared expert wider than the routed experts beside the stack #1612, hip: decode router over the bf16 rows the checkpoint holds #1614 and hip flashnext: WMMA sparse attention for prompt chunks (sparse=wmma) #1622 (prompt tiles,shared expert, decode router, sparse attention) and hip: 4096-row prompt chunks by default on the RDNA 3.5 iGPUs #1651 (a 4096-row default chunk for the RDNA 3.5 iGPUs; commit 5 sets 4,096 rows for Flash Next).
mainin one file: perf(hip): wide stream rounds reuse cached weights, and a chunk's code pairs are made once #1694 (stream tile) and perf(hip): prompt GEMMs write the activation type, not fp32 and a cast #1685 (prompt GEMMoutput).
zig/src/core/lanes/depth.zig).docs/kernel-contract.md, append only).#1702, #1613, #1615 and #1611 merge cleanly with the series. #1675, #1394, #1391-#1393, #1381 and #1425 conflict with
mainalready, and the series adds no conflict to them. We will rebase or split onto whatever lands first.ATC: issue #1661 is claimed, with anonymous session 220947162292872.
🤖 Generated with Claude Code