|
1 | 1 | # SlimServe Optimization Status |
2 | 2 |
|
| 3 | +## 2026-10-15 - PRs #55/#56 (Qwen GGUF GDN head layout, embedded MTP heads) validated on one MI300X; the ROCm launch_pdl boot break (#89) |
| 4 | + |
| 5 | +- Scope: the `qwen38-q2kxl-1` mi300x record (TP1, the registered DFlash2 |
| 6 | + k=3 drafter through `--spec`, Qwen3.8-27B-UD-Q2_K_XL.gguf) on one card of |
| 7 | + the 8x MI300X box, native ROCm build of main's csrc (the PRs touch no |
| 8 | + native code). Heads validated: #55 at 0bfc84736f (main 74b5cb8b61 merged |
| 9 | + in, plus the CPU test fix below), #56 at 6887994ab2 (#55 merged in). The |
| 10 | + arms ran on local branches `val-main` = main af8026706 + the #89 fix and |
| 11 | + `val-pr56` = #56 + the #89 fix. |
| 12 | +- Blocker first, on main rather than the PRs: since #29 every GDN/KDA |
| 13 | + profile died at boot on ROCm with `KeyError: 'Keyword argument launch_pdl |
| 14 | + was specified but unrecognised'`. The KDA / causal_conv1d / gate-projection |
| 15 | + Triton kernels passed `launch_pdl=_PDL` as a launch option on every |
| 16 | + backend; CUDA accepts the keyword (the A100 validation never saw it), the |
| 17 | + ROCm backend rejects it even when False. Fix: `PDL_LAUNCH = |
| 18 | + {"launch_pdl": True} if PDL else {}` in `vllm/triton_utils/pdl.py`, |
| 19 | + splatted at the seven launch sites, the pattern the minimax index_topk |
| 20 | + launches already used. PR #89, merged ad61e06c2. |
| 21 | +- Tests: the two PR suites on the box 25 passed / 1 skipped after pinning the |
| 22 | + torch GEMM in the CPU module check (on a ROCm host the unquantized linear |
| 23 | + dispatches CPU tensors to `vllm::rocm_unquantized_gemm`, which has no CPU |
| 24 | + kernel; commit 0bfc84736f); tests/slimserve 307 passed. After merging main |
| 25 | + 0eb1fc4d4d into #55 (only overlap: tests/kernels/mamba/test_gdn_fused_mtp.py, |
| 26 | + merged clean) the GDN layout and fused-MTP suites pass on a Mac CPU |
| 27 | + (18 passed, 1 skipped). |
| 28 | +- Arm M (main + #89) and arm P (#56): text, reasoning, image and tool |
| 29 | + canaries pass on both; model load 20.79 GiB and KV pool 1,202,879 tokens |
| 30 | + on both (the PR dequantizes nothing); boot about 30 s longer on the PR |
| 31 | + (load-time untiling of the GGUF tensors). |
| 32 | +- Parity: prompt_logprobs over four 3000-character slices of |
| 33 | + benchmarks/sonnet.txt (3128 tokens). Main vs PR: mean |dlogprob| 0.041 |
| 34 | + nats, max 0.70, argmax agreement 3104/3128, ppl 3.2199 vs 3.2097. Noise |
| 35 | + floor from two boots of the same PR code (arm P vs arm E): 0.038 nats, |
| 36 | + max 0.68, 3092/3128, ppl 3.2097 vs 3.2196. Main and the PR are equivalent |
| 37 | + within run-to-run noise. |
| 38 | +- First exact pass (seed 42, 1000 in / 2000 out, temperature 1.0 / top-p |
| 39 | + 0.95 / top-k 20): main c1 84.40 / c8 220.15 tok/s, PR c1 73.64 / c8 |
| 40 | + 186.17 (-12.7 % / -15.4 %), which read as a regression. Attribution from |
| 41 | + the harness JSON's spec counters (steps = `spec_decode_drafts`): c1 main |
| 42 | + 642 steps at 36.91 ms, PR 754 steps at 36.02 ms; acceptance 70.5 % vs |
| 43 | + 55.0 %. The engine's interval metrics show the same drafted throughput on |
| 44 | + both arms (223.2 tok/s at c8) and acceptance climbing to 99-100 % as the |
| 45 | + ignore_eos generation falls into repetition, at different points on the |
| 46 | + two trajectories. A torch-profiler capture of a 256-token decode on each |
| 47 | + arm: kernel total 476.3 vs 468.1 ms with the PR's graph replays slightly |
| 48 | + shorter; the PR's only new kernel is the per-layer index_select (48 per |
| 49 | + step, 0.09 ms replayed / 0.70 ms eager at T=1, measured separately). |
| 50 | + Nothing in the step got slower. |
| 51 | +- Multi-seed exact pass, same boots, warmed, six seeds at c1 and three at c8 |
| 52 | + (`seeds-val-main/`, `seeds-val-pr56/`), every run exact: |
| 53 | + |
| 54 | + | arm | c1 tok/s per seed (1..6) | c1 mean | c1 ms/step | c1 accept | c8 tok/s (42 / 7 / 99) | c8 mean | c8 ms/step | c8 accept | |
| 55 | + |---|---|---|---|---|---|---|---|---| |
| 56 | + | main + #89 | 87.07 / 91.46 / 90.62 / 70.92 / 94.03 / 74.61 | 84.8 | 37.13 | 71.6 % | 199.85 / 209.63 / 217.26 | 208.9 | 14.45 | 67.3 % | |
| 57 | + | #56 | 89.91 / 88.34 / 84.01 / 84.68 / 88.29 / 83.82 | 86.5 | 36.17 | 70.9 % | 210.50 / 212.34 / 200.34 | 207.7 | 14.60 | 67.8 % | |
| 58 | + |
| 59 | + (c8 ms/step is wall / total drafts, i.e. per request-step; multiply by 8 |
| 60 | + for the batch step.) Decision: no regression. Per-step cost is equal (PR |
| 61 | + 2.6 % faster at c1, 1 % slower at c8, both inside the seed spread); the |
| 62 | + single-seed gap was draft acceptance on seed 42's trajectory. The |
| 63 | + recorded V2 DFlash2 baseline of 2026-08-25 (c1 ~75.5 / c8 194-197.5) sits |
| 64 | + inside the same spread. |
| 65 | +- Methodology note: with ignore_eos and 2000 output tokens a sampled |
| 66 | + generation collapses into repetition and DFlash acceptance goes to 100 %, |
| 67 | + so one seeded exact number on this profile carries about +-12 % of |
| 68 | + trajectory noise (70.9 to 94.0 tok/s across six seeds on main). A/B |
| 69 | + comparisons on this record need several seeds, or the per-step time from |
| 70 | + the spec counters; the registered c1/c8 numbers should be read with that |
| 71 | + spread. |
| 72 | +- Arm E (#56's feature: the GGUF's embedded NextN head served as an MTP |
| 73 | + drafter, k=2, through a validation-only registry edit reverted afterwards; |
| 74 | + the GGUF carries `qwen35.nextn_predict_layers=1` and four |
| 75 | + `blk.64.nextn.*` tensors): boots with method=mtp, canaries pass, pool |
| 76 | + 1,426,371 tokens, seed-42 c1 77.06 / c8 201.51 (32.60 / 11.96 ms per |
| 77 | + step, acceptance 75.6 % / 70.5 %). Single seed, so not ranked against the |
| 78 | + DFlash2 drafter; the registered drafter stays. |
| 79 | +- Raw (on the MI300X box): `perf/results/2026-10-15/pr5556-mi300x/`: |
| 80 | + armM/, armP/, armE/ (exact JSON, warmups), `*-server.log`, `*-parity.json`, |
| 81 | + `profile-val-main/`, `profile-val-pr56/` (traces + profiler tables), |
| 82 | + `seeds-val-main/`, `seeds-val-pr56/`; driver scripts and logs in |
| 83 | + `~/.local/scratch/pr5556/`. |
| 84 | + |
3 | 85 | ## 2026-10-14 - PR #86 (LTX-2.5 on Apple Silicon) render and serve check on a Mac Studio M4 Max |
4 | 86 |
|
5 | 87 | - Box: Mac Studio M4 Max (40-core GPU, 128 GiB, macOS 27.0.1), Xcode 27.0 |
|
0 commit comments