docs: record Dankserver VRAM/RAM growth investigation (2026-08-14)
This commit is contained in:
1 parent
9d7643ec5d
commit
bea52138d2
3 files changed
+133
No files matched your search
@@ -0,0 +1,128 @@
|
|||||||
|
---
|
||||||
|
type: reference
|
||||||
|
title: Dankserver VRAM and RAM Growth Under Load
|
||||||
|
description: Investigation of the recurring cuBLAS crash on frank-default-small. What grows, what does not, and what to do next.
|
||||||
|
tags:
|
||||||
|
- dankserver
|
||||||
|
- llamacpp
|
||||||
|
- vram
|
||||||
|
- ram
|
||||||
|
- ctx-checkpoints
|
||||||
|
- crash
|
||||||
|
---
|
||||||
|
|
||||||
|
# Dankserver VRAM and RAM Growth Under Load
|
||||||
|
|
||||||
|
This page records the investigation of the recurring cuBLAS crash on
|
||||||
|
`frank-default-small` (llama.cpp, RTX 3090 24 GiB). The service aborts
|
||||||
|
with `CUDA error: an unsupported value or parameter was passed to the
|
||||||
|
function` in `cublasSgemm_v2` at `ggml-cuda.cu:1541` during
|
||||||
|
`update_slots` -> `decode` -> `process_ubatch`. It crashed on 2026-08-13
|
||||||
|
at 19:45 and 19:55 and on 2026-08-14 at 12:00:43.
|
||||||
|
|
||||||
|
## What Was Ruled Out
|
||||||
|
|
||||||
|
### ctx-checkpoints do not grow VRAM
|
||||||
|
|
||||||
|
`--ctx-checkpoints 4` stores context checkpoints in host RAM. The log
|
||||||
|
records every checkpoint at exactly 62.813 MiB. The size never grows.
|
||||||
|
The reasoning:
|
||||||
|
|
||||||
|
- `common_prompt_checkpoint` (common/common.h) stores the serialized KV
|
||||||
|
state in `std::vector<uint8_t>` fields. These live on the host heap.
|
||||||
|
- `update_tgt()` and `update_dft()` call `llama_state_seq_get_data_ext`
|
||||||
|
with `LLAMA_STATE_SEQ_FLAGS_PARTIAL_ONLY`. The serialized state moves
|
||||||
|
from VRAM to RAM for the snapshot and back on restore.
|
||||||
|
- With 4 slots and `--ctx-checkpoints 4`, the maximum checkpoint RAM is
|
||||||
|
16 x 62.813 MiB, about 1.0 GiB. That is fixed and small.
|
||||||
|
- `data_spec` (spec-decode state) is empty for ngram-mod. The ngram-mod
|
||||||
|
implementation does not override `get_state()`.
|
||||||
|
|
||||||
|
### ngram-mod does not grow VRAM
|
||||||
|
|
||||||
|
ngram-mod allocates one fixed 64 MiB CPU hash table
|
||||||
|
(`common_ngram_mod::entries`, 16M int32 entries). It never resizes. The
|
||||||
|
matcher keeps about 12 bytes per sequence. Draft generation runs on the
|
||||||
|
CPU. The speculative path allocates zero GPU memory.
|
||||||
|
|
||||||
|
### The CUDA graph cache has eviction in this build
|
||||||
|
|
||||||
|
`ggml_backend_cuda_context::cuda_graph()` sweeps every 5 seconds and
|
||||||
|
evicts graphs unused for 10 seconds. Upstream issue #25082 describes an
|
||||||
|
unbounded graph cache, but build b10108-13-g555881ebc includes the
|
||||||
|
eviction sweep. This build does not exhibit that leak.
|
||||||
|
|
||||||
|
## What Grows
|
||||||
|
|
||||||
|
### RAM growth is suspected, not yet confirmed
|
||||||
|
|
||||||
|
systemd reported MemoryPeak 46.9 GiB for the crashed process and 45.9
|
||||||
|
GiB for the replacement. RSS is flat at 32.3 GiB, which matches the
|
||||||
|
documented idle baseline of about 32 GiB. The difference is file-backed
|
||||||
|
page cache from the `--no-mmap` model read; cgroup memory.current counts
|
||||||
|
file pages attributed to the process. That gap is not proof of a leak by
|
||||||
|
itself.
|
||||||
|
|
||||||
|
The upstream pattern to watch is issue #26216: the prompt cache and
|
||||||
|
checkpoint accumulation exceed the `--cache-ram` cap and do not plateau.
|
||||||
|
The environment file does not set `--cache-ram`, so the llama.cpp
|
||||||
|
default of 8192 MiB applies. The monitor logs RSS, which separates
|
||||||
|
anonymous memory from file cache. If RSS climbs under load while VRAM is
|
||||||
|
flat, the RAM-side accumulation is real.
|
||||||
|
|
||||||
|
### VRAM suspects under load
|
||||||
|
|
||||||
|
VRAM is flat at idle: 21,268 MiB across every monitor sample. The crash
|
||||||
|
correlates with load density and slot context size (143K tokens on
|
||||||
|
slot 2), not with wall-clock time. The two mechanisms worth testing:
|
||||||
|
|
||||||
|
1. Flash-attention F16 K conversion workspace. The prefill kernel on
|
||||||
|
Ampere is `MMA_F16`. It converts the quantized K cache (q8_0) to F16
|
||||||
|
for the attention math. The workspace size scales with the attended
|
||||||
|
context length (`ggml_nelements(K) x 2`). It is allocated into the
|
||||||
|
graph buffer via `ggml_cuda_flash_attn_ext_get_alloc_size`.
|
||||||
|
2. The CUDA VMM pool grows monotonically. `ggml_cuda_pool_vmm::alloc`
|
||||||
|
only reserves more physical memory; `free` only releases the
|
||||||
|
reservation slot. The pool never shrinks during the process
|
||||||
|
lifetime. Any new peak allocation permanently expands VRAM usage.
|
||||||
|
|
||||||
|
Both match the observed pattern: growth under prefill bursts at deep
|
||||||
|
context, flat at idle, crash when a burst exceeds the ~2.8 GiB headroom.
|
||||||
|
|
||||||
|
## Monitoring
|
||||||
|
|
||||||
|
The monitor runs on Dankserver:
|
||||||
|
|
||||||
|
```
|
||||||
|
/home/dank/vram-monitor.sh
|
||||||
|
/home/dank/vram-log.csv
|
||||||
|
```
|
||||||
|
|
||||||
|
It samples GPU VRAM and process RAM every 10 seconds and appends a CSV
|
||||||
|
row. The columns are timestamp, uptime, GPU VRAM MiB, GPU utilization,
|
||||||
|
process RSS, process VSZ, and systemd MemoryPeak.
|
||||||
|
|
||||||
|
## Mitigation Options
|
||||||
|
|
||||||
|
The documentation for the benchmark ([[frank-default-small-benchmark]])
|
||||||
|
prescribes the first option for this crash class. None of these change
|
||||||
|
the model.
|
||||||
|
|
||||||
|
| Option | Effect | Cost |
|
||||||
|
| ------ | ------ | ---- |
|
||||||
|
| `GGML_CUDA_FORCE_MMQ=1` | Bypasses the cuBLAS path in the crashing function | Slight decode slowdown |
|
||||||
|
| `--cache-ram 2048` | Bounds the confirmed RAM growth | Cache misses on prompt reuse |
|
||||||
|
| `--ctx-checkpoints 2` | Cuts checkpoint RAM and save cost in half | More prefill work after eviction |
|
||||||
|
| Apply PR #24649 | Clears slot checkpoints before the prompt-cache save | Needs a llama.cpp rebuild |
|
||||||
|
|
||||||
|
Upstream references: issue #26216 (prompt cache growth), issue #25082
|
||||||
|
(graph cache, not applicable to this build), issue #23635 (quantized KV
|
||||||
|
with speculative decoding), PR #24649 (checkpoint-to-cache duplication),
|
||||||
|
PR #25649 (slot checkpoints freed on prompt clear, merged), issue #26119
|
||||||
|
(same cuBLAS signature, confirmed on V100 with speculative decoding).
|
||||||
|
|
||||||
|
## See Also
|
||||||
|
|
||||||
|
- [[frank-default-small-benchmark]]
|
||||||
|
- [[Dankserver System Specs]]
|
||||||
|
- [[deployment]]
|
||||||
@@ -188,6 +188,10 @@ The user reported that on `frank-default-large` (Dankclaw), a job that is stream
|
|||||||
|
|
||||||
Diagnosis recipe: to tell a client abort from a server release, read the journal around the release time. A client abort shows `W srv stop: cancel task, id_task = N`. A natural stop shows only `slot release` with `truncated = 0` and the final timings line.
|
Diagnosis recipe: to tell a client abort from a server release, read the journal around the release time. A client abort shows `W srv stop: cancel task, id_task = N`. A natural stop shows only `slot release` with `truncated = 0` and the final timings line.
|
||||||
|
|
||||||
|
### VRAM and RAM growth under load
|
||||||
|
|
||||||
|
This crash class recurs on Dankserver. The 2026-08-14 investigation ruled out ctx-checkpoints and ngram-mod as VRAM growth sources and confirmed RAM growth. See [[dankserver-vram-growth]] for the full findings, the monitoring setup, and the mitigation options.
|
||||||
|
|
||||||
## See Also
|
## See Also
|
||||||
|
|
||||||
- [AGENTS.md](../AGENTS.md) — the git workflow rules
|
- [AGENTS.md](../AGENTS.md) — the git workflow rules
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ MTP-ONLY draft, port 7770]
|
|||||||
- [[Running Qwen3.6 27B FP8 on Dankclaw]] — Dense model (27B) on Strix Halo APU
|
- [[Running Qwen3.6 27B FP8 on Dankclaw]] — Dense model (27B) on Strix Halo APU
|
||||||
- [[frank-default-large-benchmark]] — backend/spec benchmark; chose MTP sidecar (2026-08-14) over DFlash (parallel premature-EOS bug)
|
- [[frank-default-large-benchmark]] — backend/spec benchmark; chose MTP sidecar (2026-08-14) over DFlash (parallel premature-EOS bug)
|
||||||
- [[frank-default-small-benchmark]] — ncmoe and batch/ubatch sweep that drove the Dankserver state
|
- [[frank-default-small-benchmark]] — ncmoe and batch/ubatch sweep that drove the Dankserver state
|
||||||
|
- [[dankserver-vram-growth]] — VRAM/RAM growth investigation behind the recurring cuBLAS crash on frank-default-small
|
||||||
- [[Dankclaw Improvements]] — researched enhancements: self-hosted agentic tools, runtime tuning, server/OS settings
|
- [[Dankclaw Improvements]] — researched enhancements: self-hosted agentic tools, runtime tuning, server/OS settings
|
||||||
|
|
||||||
## Speculative Decoding & Quantization
|
## Speculative Decoding & Quantization
|
||||||
|
|||||||
Reference in new issue
Block a user