改动 / #3484
#3484 [Engine] prefill: a padded activation is gfx11 only, and Gemm::native copies it unpadded instead of exiting
open · @John-Pi · 0 评论 · 去 GitHub 看
BenchmarksServer & APIAMD / HIPNVIDIA / CUDAModels & quantsDocumentationWindows
说明
## Problem and result `STRATA_PF_PAD=1 STRATA_PF_GEMM=1` pads the two K 6144 producers' activation row stride to 6,208 for the prompt GEMM. The only product that reads a padded stride is `strata_pf_gemm_f16_ld`, which is compiled into `wmma_gemm.cu`'s **gfx11 matrix-core block** and returns `false` on every other arch. On an RDNA4 card `Gemm::native` therefore fell through to its "a padded X … needs STRATA_PF_PAD's path" branch and called `std::exit(1)` — under `serve/`, one engine restart per request. Before: **the engine exits** on the first prompt GEMM. After: the producer does not pad where no kernel reads the stride (one line at the first prompt), and if a padded X does arrive from anywhere (`Gemm::native` is public), its rows are copied unpadded and the ordinary paths run — same products, same bits. ``` # before (0.1.45 binary, RX 9070, gfx1201) prefill gemm: a padded X (ldx 6208, K 6144) needs STRATA_PF_PAD's path exit 1 # after, STRATA_PF_PAD=1 STRATA_PF_GEMM=1 prefill gemm: STRATA_PF_PAD needs the padded gfx11 product, which this card does not run; not padding … prompt and decode complete, exit 0 ``` ## Related discussion None: no issue tracks this (the `#0` placeholder in my earlier note was never a real number). `STRATA_PF_GEMM` itself is discussed in #1386 and #1478, both closed and about other arches; neither covers the padded-activation exit. Say the word if you would rather have this as an issue first. ## Approach - **`strata_pf_padded_gemm_available()`** (`wmma_gemm.h/.cu`) answers whether the padded product exists on the current device: the same gfx11 list the kernels are compiled for, and a hard `false` in a build with no gfx11 target (`inline false` outside HIP). It sits next to `strata_wmma_gfx11_device()` so the two answers cannot drift. - **`prefill.cpp`**'s `pf_pad()` asks it before padding, and prints one line when the env asks for a product this card has not — the alternative was padding for a kernel that will never be there. - **`Gemm::unpad_x()`** (`gemm.cu/.hpp`): a padded X no kernel took is copied to a contiguous FP16 buffer of stride K — one `cudaMemcpy2DAsync`, one grow-only buffer per `Gemm` — and `native()` recurses on it. `exit(1)` remains only for a failed allocation, and its message now says that. - The `native()` recursion passes `beta = 0` as the original call did, so the products and their accumulate are unchanged. - `docs/AMD_HIP.md`: one bullet in the RDNA4 section with the reproduction, the numbers below, and what was not tested. Compatibility: nothing changes when `STRATA_PF_PAD` is unset (the default), on gfx11 (where the padded product exists and `pf_pad()` behaves as before), or for any CUDA or SYCL build (`strata_pf_padded_gemm_available()` is `false`, `pf_pad()` is already off on those arches). ## Validation **Passed:** - Build: `cmake --build build-hip -j$(nproc)` — 338 of 338, Release, `CMAKE_HIP_ARCHITECTURES=gfx1201`, RX 9070 (gfx1201, 16 GB), system ROCm 7.2.4, kernel 7.2.11, engine 0.1.46.1 at `9ae93f7b` + this change. - `ctest --test-dir build-hip -j4` — 77 of 79 (see Failed for the two). - The prompt runs to completion with `STRATA_PF_PAD=1 STRATA_PF_GEMM=1`, and its 8 greedy tokens are **identical** to the run without the switch (1,199-token prompt, `--spec 4 --prefill 2048 --kv k8v4`, Coder IQ1_M): ``` output : 13 271 248046 198 248045 74455 198 248068 # both runs ``` - **The copy path is exercised**, not just the gate: rebuilt with the availability check forced open (so the producers really write stride 6,208 and `Gemm::native` takes the padded branch), the run still prints no exit, no "needs STRATA_PF_PAD's path", and the same 8 tokens. The temporary patch is not part of the diff. - No regression when the switch is off: every other arm above is byte-identical in its output, and the engine was run 6 times on this change. **Failed:** - **Before** this change, the same command on the 0.1.45 binary (`engine/strata.bak-0.1.45-pre-gemmfix`, same pack, same prompt) exits 1 with `a padded X (ldx 6208, K 6144) needs STRATA_PF_PAD's path` — the reproduction. No output tokens. - `ctest`: `ple_parity` (wants `../../Q2_0/Qwen3.8-Flash-Next-GSQ-RCO-Q2_0-00002-of-00002.gguf`, not on this machine) and `hip_prefill_mmq_parity` (its APR block calls `ggml_type_name(145)` while the TQ overlay leaves `GGML_TYPE_COUNT` at 43 → out-of-bounds `type_traits[]` read → `basic_string: construction from null is not valid`). Both fail identically on `origin/main` here; neither file is touched. **Not run:** - **CUDA and SYCL.** `src/prefill/gemm.cu`, `gemm.hpp` and `prefill.cpp` are shared with the CUDA build (SYCL takes the sources from `src/` too) and this machine has no `nvcc`, so I could not build them. The changed code is host-side and arch-gated, and `strata_pf_padded_gemm_available()` is `false` there, but it is unbuilt on those backends. - **gfx11.** I have no gfx11 card, so the arm where the padded product actually exists (and `pf_pad()` must keep padding) is unmeasured — the `false`/`true` answers come from the same arch check the kernels are compiled against, and that is all I can claim. - Windows, and any pack other than Coder IQ1_M. ## Limits - `STRATA_PF_GEMM=1` stays inert on RDNA4 rather than becoming useful: it needs a gfx11 matrix-core product, and writing one for gfx12 is a separate piece of work. With the gate in place the switch alone measured 1,247 against 1,243 tok/s at 4K and 1,330 against 1,321 at 8K (medians of 3 starts) — noise. - The `unpad_x()` fallback costs one D2D copy of the activation (`T x K` FP16, ~14 MiB at a 1,199-token chunk) when it fires. It only fires for a padded X that no kernel took, which after this change means a caller that pads without asking — i.e. it is a safety net, not a path I recommend. - `docs/AMD_HIP.md`: I put the bullet in the RX 9070 (RDNA4) list; if you would rather keep that list for shipped defaults only, move it to the closer/deep-context notes and I will follow.
本站相关内容
相关页面的快捷入口。