Skip to content

ds4f-q2-q4 cannot be served resident on 128 GB DGX Spark (GB10) — global OOM during startup span preparation #705

Description

@adamlawi

Environment

  • NVIDIA DGX Spark, GB10 (sm_121), 128 GB unified memory, aarch64
  • Ubuntu 24.04.4, kernel 6.17.0-1029-nvidia, driver 580.173.02, CUDA 13.0.88
  • ds4 built from 6747e77 with make cuda-spark, no local changes
  • Models from ./download_model.sh: ds4f-q2 (80.76 GiB) and ds4f-q2-q4 (90.89 GiB)

Summary

ds4f-q2 works well. ds4f-q2-q4 cannot be started resident at all on this machine: every
attempt is killed by the kernel OOM killer during the startup tensor-span preparation phase, before
the memory plan is even printed. Context size is not the factor — it fails identically at
--ctx 100000, --ctx 16384 and --ctx 4096.

download_model.sh describes this quant as "Works on DGX Spark but loading may struggle compared
to ds4f-q2"
, which understates it for the 128 GB configuration.

Reproduction

./download_model.sh ds4f-q2-q4
./ds4-server -m gguf/DeepSeek-V4-Flash-Layers37-42Q4KExperts-...-fixed-0731.gguf \
  --host 0.0.0.0 --port 8888 --ctx 16384 --cors

Result: Killed (SIGKILL, exit 137). Last lines before death:

ds4: built 456 aligned CUDA artifacts (68.58 GiB) in 18.9s; expert raw residency replaced
ds4: CUDA aligned artifacts replace expert residency; leaving the 90.89 GiB model mmap unpinned
ds4: CUDA preparing model tensor mappings
ds4: CUDA loading model tensors into device cache
ds4: CUDA loading model tensors 16.01 GiB cached
ds4: CUDA prepared model tensor mappings 16.88 GiB
<killed>

What we tried (all resident attempts)

Mode ctx Result
ds4-bench 8321 passed, but startup span phase took 296 s
ds4 --perplexity-file 32768 OOM-killed
ds4 --perplexity-file 16384 OOM-killed
ds4 --perplexity-file 4096 OOM-killed (1882-token input)
ds4-server 100000 OOM-killed
ds4-server 16384 OOM-killed

--ssd-streaming is the only mode that starts reliably, but decode drops to ~1.2 t/s
(80 tokens in 66 s), versus 14.7 t/s for resident ds4f-q2.

The measurable difference

The startup phase that precedes the memory plan differs by 3.5x in volume and 120x in time:

Model startup model preparation covered time
ds4f-q2 (server and bench) 8.20 GiB of tensor spans 2.2 s
ds4f-q2-q4 (bench, survived) 28.45 GiB of tensor spans 296 s
ds4f-q2-q4 (server) reached 16.88 GiB, then killed

The 296 s for a phase that takes 2.2 s with ds4f-q2 suggests the surviving run was already
thrashing at the memory ceiling; the server runs crossed it.

Likely cause

cuda/mmq/ds4_repack.cu has aligned repack builders for exactly three tensor classes, each gated on
the tensor type:

  • ds4_repack_iq2_candidatetype == 16 (IQ2_XXS), .ffn_gate_exps / .ffn_up_exps
  • ds4_repack_q2k_candidatetype == 10 (Q2_K), .ffn_down_exps
  • ds4_repack_q8_candidate — Q8_0 dense

There is no Q4_K candidate or builder. In ds4f-q2-q4 the routed experts of layers 37–42 are
Q4_K, so they get no aligned artifact and must be pulled into the device cache in raw form. On GB10
the CPU and GPU share one 128 GB pool, so 68.58 GiB of artifacts plus ~20 GiB of raw Q4_K spans plus
the model mapping exhausts it.

--ssd-streaming reports the same split from the other side:

SSD streaming mixed-precision model: 6/43 routed layers off the slab size class
will bypass the expert cache and read experts via mapped model views

Note this appears to be a different gap from the mmq prefill one: q4k_path && n_tokens > 1u
(ds4_cuda.cu:23961) is live in this build, and prefill does work — it is just slower
(548 t/s vs 872 t/s for ds4f-q2 at 8k). So the missing piece is the aligned/SoA residency path,
not the mmq prefill kernels.

Kernel OOM record

Killed process 124531 (ds4-server) total-vm:279950520kB, anon-rss:968kB
oom-kill:constraint=CONSTRAINT_NONE,...,global_oom
Node 0 Normal free:29852kB ... active_file:32kB inactive_file:720kB

Global OOM with page cache already drained to ~0 — nothing left to reclaim. Because ds4 sets
oom_score_adj=1000 it dies first, which is good, but the same event also took down unrelated
desktop-session processes (pipewire, dbus-daemon, kactivitymanage).

Speed and quality data, for context on whether this is worth fixing

Same prompt file, 128 generated tokens per frontier, ds4-bench:

ctx q2 prefill q2-q4 prefill q2 decode q2-q4 decode
2048 790.7 459.7 17.31 13.57
4096 881.5 553.8 14.92 10.04
6144 875.7 556.2 14.83 9.59
8192 872.1 547.6 14.69 9.47

Quality on an identical 1882-token sample: ds4f-q2 ppl 11.108, ds4f-q2-q4 ppl 10.841
(the latter measured under --ssd-streaming, since resident mode OOMs; weights are identical so
the number should be unaffected).

Suggestions

  1. If a Q4_K aligned repack path is not planned, consider changing the download_model.sh wording
    for ds4f-q2-q4 — on a 128 GB DGX Spark it does not "struggle to load", it cannot load resident.
  2. A startup pre-flight check comparing the projected span volume against available unified memory
    would turn an OOM kill into a clear error message.

Happy to run further diagnostics on this machine — it is a stock DGX Spark and we can rebuild
and retest on request.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions