Files
k3s-cluster/llamacpp/args-deepseek-v4-flash-0731.md
2026-08-18 18:56:07 +02:00

7.8 KiB
Raw Permalink Blame History

Deployment arguments — deepseek-v4-flash-0731 (RETIRED)

Historical reference for the llama-server flags used by the retired deployment-deepseek-v4-flash-0731.yaml. The Deployment can be recovered from git history if this model is needed again.

Model & source

  • Model: deepseek-ai/DeepSeek-V4-Flash-0731 (DeepSeek-V4-Flash, 0731 weights)
  • Quantization: unsloth/DeepSeek-V4-Flash-0731-GGUFUD-IQ1_M (Unsloth Dynamic IQ1_M), split across 3 shards (~87 GiB total):
    • DeepSeek-V4-Flash-0731-UD-IQ1_M-00001-of-00003.gguf
    • DeepSeek-V4-Flash-0731-UD-IQ1_M-00002-of-00003.gguf
    • DeepSeek-V4-Flash-0731-UD-IQ1_M-00003-of-00003.gguf
  • HuggingFace repo: https://huggingface.co/unsloth/DeepSeek-V4-Flash-0731-GGUF
  • Image: ghcr.io/ggml-org/llama.cpp:server-vulkan (floating tag — deepseek4 is a brand-new arch; pin to a specific server-vulkan-bXXXX once verified).

Hardware target

NUCBox APU — AMD Ryzen AI Max 395 (Strix Halo), Radeon 8060S (RDNA 3.5), ~120 GiB unified memory split by firmware into ~90 GiB VRAM and ~30 GiB CPU RAM. Pinned via nodeSelector: {kubernetes.io/arch: amd64, hardware: high-memory}.

Why this model nearly fills the machine

The UD-IQ1_M model is ~87 GiB, almost the entire 90 GiB VRAM pool. Unlike the old Qwen models (1620 GiB, fully offloaded with room to spare), this one cannot be fully offloaded to the GPU: putting all 43 layers + the KV cache + Vulkan compute buffers in VRAM would exceed 90 GiB. The tuning below is all about fitting the model while leaving headroom for the KV cache, compute buffers, and co-resident pods.

Argument-by-argument

Flag Value Meaning
-m /models/DeepSeek-V4-Flash-0731-UD-IQ1_M-00001-of-00003.gguf Model file. Pointed at the first shard only; llama.cpp auto-discovers and loads -00002-… / -00003-… from the same directory.
--alias deepseek-v4-flash-0731 Name reported by GET /v1/models. Must match the model_name in litellm/litellm.yaml so LiteLLM routes to this server.
--host 0.0.0.0 Bind on all interfaces so the k8s Service can reach the pod.
--port 8080 Listen port (matches containerPort + Service targetPort).
--jinja (flag) Use the chat template baked into the GGUF (DeepSeek-V4 DSML format, with thinking/reasoning support). Reasoning comes back in reasoning_content.
-ngl 38 GPU layer offload. Offload 38 of 43 layers to the GPU. See “VRAM budget” below — full offload would OOM, and the f16 KV cache (no Flash Attention on Vulkan) is larger than q8_0 would be, so 38 (not 40) layers are offloaded to leave ~5 GiB VRAM headroom. 5 layers (~10 GiB) run on CPU RAM.
-c 65536 Total KV-cache context window (64k, the required minimum). Single slot gets the full window.
-np 1 Parallel slots. 1 slot ⇒ the full 64k goes to a single concurrent request.
--cont-batching (flag) Continuous batching across slots (no-op with 1 slot, but harmless and correct if -np is raised).
--cache-type-k f16 f16 K cache (NOT quantized). The Vulkan backend has no Flash Attention for the deepseek4 arch, and quantized V cache requires Flash Attention (llama.cpp hard-errors otherwise). Additionally, deepseek4/MLA models require K and V cache types to be identical, so K cannot be quantized either.
--cache-type-v f16 f16 V cache. Same reason — quantized V cache needs Flash Attention, which Vulkan lacks for deepseek4.
--temp 1.0 Default sampling temperature (DeepSeek-V4 recommendation). Clients may override per request via the OpenAI API.
--top-p 0.95 Default nucleus-sampling threshold (DeepSeek-V4 recommendation). Overrideable per request.
--threads 8 CPU threads for sampling + the 5 CPU-resident layers.

VRAM budget (90 GiB pool)

The model (~87 GiB IQ1_M) is almost the size of the entire 90 GiB VRAM pool, so it cannot be fully offloaded: -ngl 999 would try to put all 43 layers into VRAM and overflow once the KV cache + Vulkan compute buffers are added. Instead -ngl 38 offloads 38 of 43 layers to the GPU and keeps 5 layers (~10 GiB) on CPU RAM, leaving ~5 GiB of VRAM headroom for the KV cache, compute buffers, and fragmentation.

KV cache is f16, not q8_0 — the Vulkan backend has no Flash Attention for deepseek4, and quantized V cache requires Flash Attention (llama.cpp hard-errors: "quantized V cache was requested, but this requires Flash Attention"). deepseek4/MLA models also require K and V cache types to be identical, so K cannot be quantized either. f16 KV at 64k is ~5.7 GiB (MLA KV: 576 K + 512 V elements/token/layer × 43 layers × 65536 tokens × 2 bytes).

Approximate VRAM usage:

Component VRAM
Weights (38 GPU layers) ~77 GiB
KV cache (f16, 64k, 1 slot) ~5.7 GiB
Vulkan compute buffers ~2 GiB
Total in VRAM ~85 GiB
Headroom (of 90 GiB) ~5 GiB

5 layers (~10 GiB) live in CPU RAM (counted against the pod's cgroup memory limit, not VRAM). VRAM is exclusive to this model (no other pod uses it); the other NUCBox pods only compete for the 30 GiB CPU RAM.

Note: several deepseek4-specific fused ops (Lightning Indexer, HC pre/comb/post) are not yet implemented in the Vulkan backend and fall back to CPU (logged as warnings, not fatal). Inference still works; it is slower than it will be once those ops land in a future server-vulkan build.

How to tune if it OOMs / has spare headroom

  • Pod OOM-killed or Vulkan out-of-device-memory during load: lower -ngl (e.g. 36) to keep more layers on CPU, or raise the container memory limit. Remember the KV cache is f16 (cannot be quantized — no Flash Attention on Vulkan), so the only ways to free VRAM are fewer GPU layers or a smaller context window.
  • VRAM headroom looks generous in logs: raise -ngl toward 43 (full offload) and/or raise -c for larger context.
  • Need more concurrent requests: raise -np (each extra slot multiplies the f16 KV cost, ~5.7 GiB/slot at 64k), and the context per slot shrinks (-c / -np).

initContainer (fetch-model)

  • Idempotently downloads the 3 shards into the shared models PVC, skipping if all shards are already present and non-empty (pod restart / recreate).
  • Atomic, resumable downloads: each shard is fetched to a .partial file (resumable via curl -C -) and only renamed to the final name on success, so an interrupted download never leaves a half-written final file that would wrongly skip re-download.
  • Free-space check: requires ~95 GiB free on /models before downloading; fails loudly with a clear message if the hostPath disk is too small (a PVC capacity bump does not add physical space to a hostPath volume — the disk on the NUCBox must be expanded).
  • Deletes the retired Qwen3.6 GGUFs from the PVC to reclaim ~36 GiB.

Resources

requests:  cpu 1000m, memory 6Gi
limits:    cpu 4000m, memory 24Gi

VRAM (weights + KV + compute) is not counted against the cgroup memory limit — the limit only covers CPU-side overhead, the mmap'd GGUF pages for the 5 CPU-resident layers (~10 GiB, resident during inference), and reclaimable page cache during load. k8s sees ~30 GiB as the node's allocatable system RAM.

Probes

  • readinessProbe: GET /health after 30s, every 10s, 6 failures.
  • livenessProbe: GET /health after 300s (87 GiB load + Vulkan init takes several minutes), every 30s, 5 failures.

Security / GPU access

privileged: true + mounts /dev/dri (DRM render nodes) — simplest reliable way to give Vulkan access to the AMD APU on k3s without a device plugin.