Pull requests / #2189

#2189 HIP: virtual memory for --kv-grow and --vram-elastic (#533) through vmm.hpp

open · @i-Vladimir-i · 0 Kommentare · Auf GitHub

BenchmarksSetup & installServer & APIAMD / HIPNVIDIA / CUDAModels & quantsDocumentationWindowsLinux

Beschreibung

**HIP: virtual memory for `--kv-grow` and `--vram-elastic` (#533) through `vmm.hpp`**

Both switches were NVIDIA-only: `vmm.cpp` had a stub for HIP, and `expert_cache.cpp` carried a second copy of the CUDA
driver table for #533's segments and refused at open on HIP. ROCm has the same functions (`hipMemAddressReserve`,
`hipMemCreate`, `hipMemMap`, `hipMemSetAccess`, `hipMemUnmap`, `hipMemRelease`), so this ports them.

**What it changes**

- `src/core/vmm.cpp` is the one place that talks to the driver's virtual memory, for both backends: a small set of
  driver operations per backend (CUDA: the driver API through the runtime's entry points, as before; HIP: the
  runtime's `hipMem*`), and the chunks, `VmmRange` and #533's segments written once on top of it.
- HIP's chunk is the **recommended** granularity (2 MiB). The minimum one is 4 KiB on gfx1201 / ROCm 7.14.1, and
  `hipMemGetInfo` counts each 4 KiB chunk as 2 MiB, so the elastic K/V would have needed 512 times as many chunks.
  CUDA keeps its minimum (2 MiB).
- `expert_cache.cpp`'s segmented arena calls `vmm_segment_*` / `vmm_reserve` / `vmm_address_free` instead of its own
  driver table. On CUDA these are the same driver calls with the same sizes in the same order (`cuMemCreate`,
  `cuMemMap`, `cuMemSetAccess`, `cuMemUnmap`, `cuMemRelease`, `cuMemAddressFree`, the recommended granularity for the
  segments as before).
- `generate.cpp`: `--vram-elastic` is no longer refused on HIP; it stays off on **HIP on Windows** (AMD's virtual
  memory was measured on Linux only). The help line and the `VRAM` refusal no longer say NVIDIA. Docs follow.
- Tests: `vmm_test` checks the HIP chunk size; `expert_cache_segmented_test` runs on HIP instead of skipping.

**What it leaves alone:** the default path (without `--kv-grow` / `--vram-elastic` nothing calls the new code except
`vmm_available()`, which only queries); the CUDA behaviour of both switches; the gfx906 compat build (no virtual
memory, as before: never measured there); every setup and server path.

**Measured before writing it** (a standalone probe on gfx1201, ROCm 7.14.1, amdgpu 6.19, Linux), because vLLM's ROCm
sleep mode needed workarounds (vllm-project/vllm#37533, #43022, #60367):

- The VRAM of a released handle is back for other programs within 10 ms by the driver's own counter
  (`mem_info_vram_used`) **while its address range stays reserved**, and `hipMemGetInfo` shows it at once. So the
  VA free-and-re-reserve cycle vLLM needed on MI300 / ROCm 7.2 is not needed here, and `VRAM`'s free-memory check reads
  the right number.
- A reservation cannot be freed in part (`hipMemAddressFree` of its tail: an error that also breaks the later full
  free), and one `hipMemSetAccess` or `hipMemcpy` cannot span two reservations (a kernel can). So, as on CUDA, one
  reservation per range.
- Small device-to-host copies (4 B to 1 MiB) from a device-only mapping work on this large-BAR card, so no host access
  is mapped (vLLM #60367 needed it on MI300 / ROCm 7.2).
- AMD's HIP docs warn that RDNA may read wrong data through two virtual aliases of one physical allocation. Neither
  user maps a chunk twice at once (the K/V maps a chunk the cache has unmapped), and `vmm_test` moves chunks that way.

**How it was checked**

- HIP (gfx1201, ROCm 7.14.1): full ctest 108/109, the one failure is `ple_parity` (needs the Q2_0 fixture, as on the
  base commit); one skip fewer than the base (`expert_cache_segmented_test` now passes). `vmm_test` and
  `expert_cache_segmented_test` pass on both cards of the box.
- Mutations, each caught: the HIP chunk at the minimum granularity (`vmm_test`), a segment unmapped but not released
  (`expert_cache_segmented_test`: "VRAM not given back"), no access set (`vmm_test` fails, the segmented test hangs).
- CUDA: the whole tree 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).
- `serve.test_vram`: 7 tests OK.
- Live, R9700 32 GB, Unsloth UD-IQ4_XS, every expert in RAM (both switches need it), `--serve`:
  - `--vram-elastic`: reserves of 4000 / 8000 / 16000 MiB took 35 / 44 / 80 ms and gave the driver 3.2 / 7.2 /
    14.7 GiB; decode 120.7 -> 119 / 114 / 98 tok/s (256-token greedy answers); `{"reserve_mib": null}` grew it back in
    0.56 s, `{"reserve_mib": 0}` to the full 10736 slots. With `--adapt-every 0 STRATA_ROUTE_RESIDENT=0` the answer
    after growing back was token for token the one before the shrink (with the adaptive tier or route-resident on, two
    identical requests already differ without any shrink, so that is the only clean comparison).
  - `--kv-grow` against the K/V window (`--kv-resident 32768`), 320-token answers, two runs each: decode at 36K
    tokens 115/115 vs 93/100 tok/s, at 78K 94/94 vs 94/94, at 156K 96/94 vs 81/88; prompt the same except one window
    run at 156K (1600 vs 2400 tok/s, the earlier window run there read at 2393); every needle found.

**Not tested:** NVIDIA at run time, Windows (HIP stays off there for `--vram-elastic`), the gfx906 build, other RDNA
cards, `--kv-grow` together with batch slots (it refuses them, unchanged).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Mehr auf der Site

Links zu Install, Modellen, Releases.