Pull requests / #1841
#1841 serve: an opt-in VRAM headroom for --expert-cache auto (#1549)
closed · @demetree · 0 コメント · GitHub で見る
Server & APIAMD / HIPNVIDIA / CUDAModels & quantsDocumentationWindows
本文
## What this changes `--expert-cache auto` sizes the VRAM-resident expert tier to every byte the card reports free. On a card that ends up nearly full that is wrong by a lot: the prompt path then reads tens of times slower while doing exactly the same work. It adds one opt-in setting and **changes no default**: ``` STRATA_EXPERT_CACHE_HEADROOM=<fraction> # "1/6", "0.17", or "0" for the sizing you have today ``` the share of free device memory `auto` keeps for the session's other buffers instead of experts. The helper is `strata::core::expert_cache_headroom()` in `include/strata/core/expert_cache.hpp`, read by the CUDA/HIP sizing in `src/program/generate.cpp`. **What it leaves alone.** The default is zero, so every backend keeps the sizing it always had and the default path is byte-identical to the last release: with the variable unset, the old expression is evaluated. An explicit `--expert-cache N` is the user's own budget and is never cut. When the headroom would leave no room at all, the old sizing stands. Nothing in the prompt, decode or expert paths is touched - the cache is just sized smaller. ## Why, and what it was measured on An Arc Pro B70 (32 GB, driver 32.0.101.8976), the Qwen3.8-Flash-Next IQ3_XXS pack, OpenCL backend, eager, `--prefill 4096`, greedy, 64-token prompt. The same 3,668 gate/up and 3,668 down naive GEMM calls at every cache size - only the cache size and the memory left over change: | expert cache | VRAM of experts | prefill | ms per expert GEMM call | |---|---|---|---| | 17,687 slots (`auto` before) | 28.82 GiB | 426 s | 111 | | 15,382 slots | 24.95 GiB | 472 s | 122 | | 14,704 slots | 23.87 GiB | 9.7 s | 2.32 | | 10,698 slots | 17.36 GiB | 10.3 s | 2.39 | A cliff, not a slope: every size up to 14,704 slots is stable at ~10 s and every size from 15,382 up takes minutes. The two expert GEMM phases are 95.8% of the GPU timeline in the slow arm, and the phase waiting for the host-to-device staging copies is **34 ms of 957,283** - the bytes are not the problem. Memory during the slow pass peaks at 31.2 GiB of dedicated memory (the card full) and holds ~15 GiB shared; the fast one peaks at 30.08 GiB dedicated and ~3.4 GiB shared. That is consistent with WDDM paging an over-subscribed allocation to system memory, which the engine's own comment at the sizing describes, but it is not proven. Ruled out, each measured: the host mirror (35% of the same pack mirrored over PCIe costs nothing, 2.05 ms per call against 2.01 with every expert resident); the prompt length (the cost is fixed per expert call, not per token); subnormals in the dequantized weights or activations (none in either pack); `--kv-resident` (7,589 ms against 7,587 ms). The kernel calls and their shapes are identical in every arm. No accuracy cost: the cut and the uncut sizing give identical greedy output tokens - eight tokens, `271 71093 271 550 18381 198 12 1510`, from a scrambled 48-token prompt. `docs/EXPERT_CACHE_HEADROOM.md` has the full findings, the A/B protocol for a card this has not been measured on, and what each outcome would mean; `docs/TEST_REQUESTS.md` gets a row for it. ## How I checked it - With the variable unset, `free_room` is the expression the last release evaluates - no code path changes. - With `1/6` set on the B70, the knob reproduces the measurement: 14,688 slots (23.83 GiB) against 17,687 (28.82 GiB) unset, with identical output tokens. - The header compiles: the SYCL build includes it and passes. - **Not compiled:** this machine has no `nvcc` or `hipcc`, so the CUDA/HIP sources in this pull request were not built where the change was written. The call site is the same statement the SYCL port makes against the same helper. ## What this is not This is not a claim that the effect is real on NVIDIA or AMD. It is Windows/WDDM evidence from one Intel card, offered as a knob so it can be measured elsewhere. If it turns out to be a no-op on CUDA the default stays zero, and if the cliff is real there the numbers from the A/B are what would justify turning it on. Closes the sizing half of #1549.
関連リンク
インストール・モデル・リリースへの站内リンク。