改动 / #2398
#2398 HIP: virtual memory for `--kv-grow` and `--vram-elastic`, on only where a start-up check passes (resubmits #2189)
open · @i-Vladimir-i · 0 评论 · 去 GitHub 看
BenchmarksSetup & installServer & APIAMD / HIPNVIDIA / CUDAModels & quantsDocumentationWindowsLinux
说明
## Title
HIP: virtual memory for `--kv-grow` and `--vram-elastic`, on only where a start-up check passes (resubmits #2189)
Issue: follows up #2189 (closed: "a check at start that turns HIP's virtual memory on only where it works"); #533;
#1475's setup now skips for the right reason.
## Summary
#2189 rebased on v0.1.44, plus a check at the first use on each GPU. HIP's virtual memory stays on only where the
runtime shows that it works. Everywhere else, `--kv-grow` and `--vram-elastic` stay off, the log says why, and the
engine runs on with the cache in one allocation. With setup's ROCm 7.10.0a20251120 wheels on an R9700 the check fails
(granularity 4 KiB). With ROCm 7.14.1 it passes.
The check also fixes a bug #2189 had on every ROCm: on Linux, ROCm keeps one open file per physical allocation. A 24 GiB
`--kv-grow` arena of 2 MiB chunks needs ~12,500 open files, so under the usual soft limit of 1,024 the cache could not
be mapped at any size.
#2399 (`--vram-elastic` with `--kv-grow`, the resubmitted #2201) is opened at the same time and builds on this one.
## What changed
Commit 1: #2189 rebased, unchanged.
- `src/core/vmm.cpp` is the one place that talks to the driver's virtual memory, for both backends (CUDA's driver API,
HIP's `hipMem*`).
- `expert_cache.cpp`'s segments go through it.
- The only conflict was the new `STRATA_GPU_METAL` guard: Metal now sits next to gfx906 (no backend).
Commit 2: the check.
- `src/core/vmm.cpp`: a per-device verdict, decided once, at the first use. On HIP it requires:
- a recommended allocation granularity of 2 MiB or more;
- 32 MiB mapped in chunks of that size to move `hipMemGetInfo`'s free memory down by about that much, and back up once
they are unmapped and released (the addresses stay reserved). One retry, in case another program moves the counter
at the same moment;
- on Linux, enough open files for every chunk of the card. The soft limit is raised as far as the hard limit allows,
and the log says so. The engine uses no `select()`, the one thing a higher limit could break.
CUDA decides as before (entry points and the device attribute), without the measurement.
- `include/strata/core/vmm.hpp`: `vmm_off_reason()`, which says what the check saw and names the HIP runtime.
`vmm_available()` / `vmm_device_supported()` answer with the verdict.
- `src/program/generate.cpp`: the reason goes into `--kv-grow is off (...; no GPU virtual memory: <reason>)` and
`--vram-elastic is off: <reason>`.
- `src/core/expert_cache.cpp`: the segmented cache's open error carries the reason.
Before, `--vram-elastic` on a driver without virtual memory failed the start. Now it falls back like the other cases,
on CUDA too.
- `tests/core/vmm_test.cpp`:
- when the GPU is "off", there is always a reason (printed with the skip);
- on HIP/Linux: the soft limit covers the card, and a range of 1,100 chunks maps whole.
- `docs/VRAM_ELASTIC.md`, `docs/DETAILS.md`: the check, the open files, and what the two ROCm versions do.
What it leaves alone:
- The default path. Without `--kv-grow` / `--vram-elastic`, nothing calls the new code (both callers short-circuit on
the switch).
- The CUDA behaviour of both switches.
- The gfx906 and Metal builds (no virtual memory).
- SYCL: the port keeps its own `vmm.cpp`, `expert_cache.cpp` and `generate.cpp`. From this change it compiles only the
two headers: `vmm.hpp` gains declarations that nothing in `sycl/` calls, and `expert_cache.hpp` changes only a
comment.
- Setup and the server.
## Extra Notes
**How it was checked.** Radeon AI PRO R9700 32 GB (gfx1201), Linux 6.8, amdgpu 6.19.14. Both ROCm versions ran on the
same machine with the same build flags (`-DCMAKE_HIP_ARCHITECTURES=gfx1201 -DSTRATA_PREFILL_MMQ=ON
-DSTRATA_BUILD_TESTS=ON`). Setup's wheels were installed from the gfx120X-all index into a venv and built with setup's
`--rocm-path` / `--rocm-device-lib-path` flags. Live runs used Unsloth UD-IQ4_XS, every expert in RAM, a 262K context,
`--kv-grow` and `"vram_elastic": true` through `serve.server`, started from a shell with the default open-file limit
(soft 1,024).
*ROCm 7.10.0a20251120 (HIP runtime 7.2.53210):*
- `vmm_test`: `no GPU virtual memory here (the recommended allocation granularity is 4 KiB, not 2 MiB or more (HIP
runtime 7.2.53210)) - skipped`. `expert_cache_segmented_test` skips (77) with the same reason. Before, both failed.
This is #1475's setup.
- Full ctest: 111 of 112. The failure is `ple_parity` (it needs the Q2_0 fixture, as on 7.14.1). In one of two runs,
`hip_prefill_native_batch` also segfaulted once; it links only the kernels, not `vmm.cpp`, and it passed in the other
run.
- Live: `--kv-grow is off (...; no GPU virtual memory: the recommended allocation granularity is 4 KiB, not 2 MiB or
more (HIP runtime 7.2.53210))` and `--vram-elastic is off: <the same>`. The cache was 9,578 slots (21.58 GiB) in one
allocation. Answers were normal, and `POST /v1/vram` got the usual 400.
- Because the granularity check fails first, the release part never ran on 7.10. The "freed 0 bytes" you saw was not
measured here.
*ROCm 7.14.1 (HIP runtime 7.14.60850):*
- Full ctest: 111 of 112 (`ple_parity`, as above). `vmm_test` and `expert_cache_segmented_test` pass.
- Live, with this PR's segments (`--kv-grow` is off next to `--vram-elastic` here, as on v0.1.44): `VRAM 4000` left
3,662 MiB free. A 30.6K-token prompt with a needle was answered right while the cache was shrunk. `VRAM 0` brought
back all 9,578 slots.
- The open-file limit: the log says `open-file limit 1024 -> 17336`. Without that raise, a fresh process mapped 1,017
chunks and then `hipMemCreate` failed; the free VRAM came back whole after each failed attempt. Under
`ulimit -Hn 4096` (with PR B's build, the same check): `--vram-elastic is off: ROCm keeps an open file per 2 MiB chunk: 17336 needed, and the open-file
limit is 4096 (hard 4096; ...)`, and the engine served with one allocation.
- Mutation: with the check leaving its chunks unreleased, the GPU is turned off with `the free VRAM fell by 32 MiB for
32 MiB mapped and rose by 0 MiB after its release`, and both tests skip.
- The default path, against v0.1.44 on the same box: both engines built the same way, run with the default flags (no
`--kv-grow`, no `--vram-elastic`), greedy, 256 tokens, two prompts, in the order v0.1.44, this, v0.1.44, this. The
answers were byte-identical: one output hash per prompt across all four runs, with decode 60.1 / 60.1 / 60.1 / 59.9
and 70.8 / 70.7 / 70.8 / 70.7 tok/s. No line about virtual memory or open files appeared.
*Other backends:*
- CUDA: builds and links with nvcc 13.4.92, `CMAKE_CUDA_ARCHITECTURES=120`, 0 errors, and no warnings in the changed
files. Not run on an NVIDIA GPU (there is none here).
- SYCL: the whole `sycl/` project (engine and parity tests, 217 targets) builds with oneAPI DPC++ 2026.1 on both
branches, 0 errors, and no warnings from the two headers. Not run: there is no Intel GPU here.
- `serve.test_vram` and `serve.test_vision_elastic` pass (14 tests).
**Not tested:** NVIDIA at run time; Windows (HIP keeps `--vram-elastic` off there, and `--kv-grow` goes through the same
check, without the open-file part); the gfx906 build; other RDNA cards; ROCm versions between 7.10 and 7.14.1.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
本站相关内容
相关页面的快捷入口。