DeepSeek-V4-Flash on DGX Spark · part 11
[DeepSeek-V4-Flash] 把前沿級開源模型搬進自己家:在 DGX Spark 上把 0731 跑起來
❯ cat --toc
TL;DR
DGX Spark(GB10)跑 DeepSeek-V4-Flash-0731 比塞進單張顯卡簡單得多:統一記憶體不用分堆,-ncmoe 那整組旗標直接跳過,你只要確認 91GB 的權重加 KV 塞得進 121 GiB。實測 decode 17.5–17.9 tok/s、context 256K、process 吃 94,252 MiB、冷啟 406 秒。而同一份 GGUF、同一個 llama.cpp commit,它只比一張二手 2080 Ti 快 7%。

前言
搬家到大房子的好處不是東西變少,是你不用再決定哪個箱子要塞進閣樓。全部擺得下,就不用分類。
上一篇我把同一顆模型塞進一張 22G 的二手顯卡,整篇的重點是怎麼決定哪些權重上卡、哪些丟一般記憶體。這次換成 DGX Spark。因為它是統一記憶體,那個問題根本不用處理。
所以這篇會短很多。後半確實有一個坑花掉我三個小時,不過先說清楚:那是我自己把環境搞髒的,不是 DGX Spark 會對你做的事。你的機器要是只裝一套 CUDA,恭喜,那節可以直接跳過——我當初要是也這麼乾淨就好了。
為什麼 DGX Spark 上這件事簡單:沒有「搬上去」這個動作
上一篇整篇在談一條分界線:哪些權重放 VRAM、哪些放一般記憶體。那條線之所以存在,是因為顯卡記憶體跟系統記憶體是兩塊分開的東西,中間隔著 PCIe。
GB10 不是這樣。它是統一記憶體——CPU 跟 GPU 共用同一塊 121 GiB,沒有「從這邊搬到那邊」這回事。
後果很直接:
-ncmoe/--n-cpu-moe這一整組旗標跳過,不用算、不用掃描、不用找邊界。- 你只需要回答一個問題:91GB 的權重,加上 KV cache 跟計算緩衝區,塞不塞得進 121 GiB?
- 答案是塞得下。實測 process 佔 94,252 MiB,載完系統還剩約 24 GiB。
上一篇那條 (VRAM − 11) ÷ 2 的算式在這裡沒有用武之地,這是好事。
我自己挖的坑:機器上有兩套 CUDA,而我只講了一半
這台機器我前前後後裝過不少東西,結果上面有兩套 CUDA,而預設路徑指向的是舊的那套:
which -a nvcc
# /usr/bin/nvcc
nvcc --version | tail -2
# Cuda compilation tools, release 12.0, V12.0.140
ls -d /usr/local/cuda*
# /usr/local/cuda /usr/local/cuda-13 /usr/local/cuda-13.2
/usr/local/cuda/bin/nvcc --version | tail -2
# Cuda compilation tools, release 13.2, V13.2.78
/usr/bin/nvcc 是 12.0,/usr/local/cuda 指向 13.2。PATH 預設吃到的是舊的那個。
我第一次編的時候有指定編譯器,自以為處理掉了:
cmake -B build -DGGML_CUDA=ON \
-DCMAKE_CUDA_ARCHITECTURES=121 \
-DCMAKE_CUDA_COMPILER=/usr/local/cuda-13.2/bin/nvcc # ← 只講了編譯器
編譯全過,零錯誤。模型也載得起來。然後第一次送 request 就死了。
那個崩潰長什麼樣子
這是當時的原文,一個字都沒改:
/home/coolthor/llama.cpp-0801/ggml/src/ggml-cuda/ggml-cuda.cu:106: CUDA error
ggml_cuda_compute_forward: SOFT_MAX failed
CUDA error: invalid argument
current device: 0, in function ggml_cuda_compute_forward at ggml-cuda.cu:2374
SOFT_MAX failed、invalid argument。這兩個詞加起來,任何人的第一個念頭都是模型或參數有問題——我也是。我去懷疑了 GGUF 檔、懷疑了 context 長度、懷疑了 0731 的新架構 llama.cpp 支援不完整。
真正指認兇手的是堆疊裡的檔案路徑:
#3 ggml_cuda_error(...) from /home/coolthor/llama.cpp-0801/build/bin/libggml-cuda.so.0
問題出在那個 .so 連到了什麼:
ldd build/bin/libggml-cuda.so | grep -E 'cudart|cublas'
# libcudart.so.12 => /lib/aarch64-linux-gnu/libcudart.so.12 ← 12!
用 13.2 的編譯器編出來的東西,跑起來連到 12 的 runtime。 CMake 照我說的用了新編譯器,但去找 runtime 函式庫的時候,自己在系統目錄裡找到了舊的那套。
為什麼是「載得進去、推論才炸」?載入階段只是配記憶體跟搬權重,那些 API 兩版之間相容;真正跑到 kernel 的時候,新編譯器產生的呼叫慣例對不上舊 runtime,才在第一個 SOFT_MAX 上碎掉。版本不對,error 卻噴在一個完全無關的地方,所以才這麼難抓。

正確的編法:把 toolkit 路徑也講死,然後用 ldd 驗
差別只有一行:
git clone https://github.com/ggml-org/llama.cpp ~/llama.cpp-0801
cd ~/llama.cpp-0801
git checkout b10217 # 我用的版本,commit ddd4ec1
cmake -B build-cuda132-sm121 -DGGML_CUDA=ON \
-DCMAKE_CUDA_ARCHITECTURES=121 \
-DCMAKE_CUDA_COMPILER=/usr/local/cuda-13.2/bin/nvcc \
-DCUDAToolkit_ROOT=/usr/local/cuda-13.2 \
-DCMAKE_BUILD_TYPE=Release
cmake --build build-cuda132-sm121 --config Release -j$(nproc)
-DCUDAToolkit_ROOT 就是那一行。CMAKE_CUDA_ARCHITECTURES=121 是 GB10 的 compute capability(sm_121),跟消費級顯卡不一樣,別抄 86 或 89。
編完先驗,不要直接跑:
ldd build-cuda132-sm121/bin/libggml-cuda.so | grep -E 'cudart|cublas'
# libcudart.so.13 => /usr/local/cuda/targets/sbsa-linux/lib/libcudart.so.13
# libcublas.so.13 => /usr/local/cuda/targets/sbsa-linux/lib/libcublas.so.13
# libcublasLt.so.13 => /usr/local/cuda/targets/sbsa-linux/lib/libcublasLt.so.13
.so.13,而且路徑在 /usr/local/cuda 底下。這一行 ldd 可以幫你省掉三個小時,因為另一條路的錯誤訊息根本不會讓你想到這裡。
一句話記起來:能編、能載都不算驗過版本;編完一定要跑 ldd。
下載:跟上一篇同一份檔案
模型部分跟上一篇完全一樣,同一個 repo、同一份量化,不重講細節:
export HF_HUB_ENABLE_HF_TRANSFER=1
hf download unsloth/DeepSeek-V4-Flash-0731-GGUF \
--include "UD-Q2_K_XL/*" \
--local-dir ~/models/ds4-0731-ud-q2-k-xl
這份模型切成三個 shard、共 91GB,第一個只有 5MB 且 n_tensors = 0(正常,不是壞檔),-m 指它就好。
服務設定:三個旗標是拿來擋 OOM 的
這是我跑著的那份:
# ~/.config/systemd/user/llama-ds4-0731-8000.service
[Unit]
Description=DeepSeek V4 Flash 0731 via llama.cpp on port 8000
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
WorkingDirectory=/home/coolthor/llama.cpp-0801
ExecStart=/home/coolthor/llama.cpp-0801/build-cuda132-sm121/bin/llama-server \
-m /home/coolthor/models/ds4-0731-ud-q2-k-xl/UD-Q2_K_XL/DeepSeek-V4-Flash-0731-UD-Q2_K_XL-00001-of-00003.gguf \
-ngl all --fit off -c 262144 \
-np 1 -ctxcp 2 -cram 2048 -b 1024 -ub 256 --no-warmup \
--host 0.0.0.0 --port 8000 \
--alias deepseek-v4-pro --reasoning-format deepseek
Restart=on-failure
RestartSec=10
TimeoutStopSec=180
[Install]
WantedBy=default.target
中間那排短旗標是這台機器的重點,值得逐個講:
-np 1 -ctxcp 2 -cram 2048 是壓住 llama-server 自己的快取用量。它預設會開多個 slot、留 32 份 context checkpoint、把 prompt 快取養到 8GB——在一般機器上這些吃的是主記憶體,無傷大雅;在統一記憶體的機器上,它們跟模型權重搶的是同一塊 121 GiB。不限制的話,送一個長 prompt 就可能讓整台直接 OOM。
-b 1024 -ub 256 縮小 prefill 的計算緩衝區,同樣是為了留餘裕。
--fit off 關掉自動配適。開著的時候 llama.cpp 會替你沒指定的參數挑值好讓東西塞得下;你明寫的 -c 它不會動。關掉是為了讓每個數值都是我自己決定的。
-ngl all 把所有層都交給 GPU。在統一記憶體上這不像獨顯那樣是「搬過去」,但仍然要明講。
context 開 256K 而不是 1M,理由是餘裕
這顆模型原生支援到 1,048,576,而我 production 設 262,144。
1M 我測過,載得起來,冷啟 416 秒。但 121 GiB 是 CPU 跟 GPU 共用的,KV 養大之後,留給作業系統跟其他服務的記憶體就會變緊。256K 載完還剩約 24 GiB,那個餘裕讓我晚上不用擔心。

另外要修正我原本的一個誤判:我曾經從 rope.scaling.factor = 16.0、original_context_length = 65536 推論「1M 是硬外推、沒訓練過」,那是錯的——DeepSeek 的技術報告說 V4 的預訓練長度一路推到 1M。最後只剩一個 caveat:長 context 的品質我沒量過。
驗收:載入要等七分鐘,別以為它掛了
冷啟實測 406 秒。這段時間 /health 會一直回 503,那是正常的:
# 1. 還在載 vs 好了
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8000/health
# 503 = 還在載入(要等,別重啟);200 = 可以用了
# 2. 參數有沒有被偷偷改掉
curl -s http://localhost:8000/props | python3 -m json.tool | grep -E 'n_ctx|build'
# n_ctx 262144 / build b1-ddd4ec1
# 3. 載的是哪顆
curl -s http://localhost:8000/v1/models | python3 -m json.tool | grep -E 'n_params|n_ctx_train'
# n_params 284334567511 / n_ctx_train 1048576
⚠️ 看到 503 不要重啟。重啟只會讓它從頭再讀 91GB,再等七分鐘。
記憶體佔用可以這樣看(GB10 的 nvidia-smi --query-gpu=memory.used 會回 [N/A],統一記憶體的怪癖):
nvidia-smi --query-compute-apps=pid,used_memory --format=csv,noheader
# 1142691, 94252 MiB
誠實對照:比那張二手顯卡快 7%
同一份 GGUF、同一個 llama.cpp commit、同一種量化,兩台機器對跑:
| 機器 | context | decode |
|---|---|---|
| DGX Spark(GB10,121 GiB 統一記憶體) | 256K | 17.5–17.9 tok/s |
| 單張改裝 2080 Ti 22G + EPYC 7402 | 1M | 16.4–16.5 tok/s |
差約 7%。
這個數字要怎麼看,取決於你想買什麼。如果你要的是吐字速度,7% 不值那個價差。DGX Spark 的優勢其實在另外兩件事:121 GiB 的空間(下一顆更大的模型還塞得下,那張 22G 的卡就不一定了),以及不用分堆的省事——上一篇有一整節在教怎麼算 -ncmoe,這篇連提都不用提。
⚠️ 邊界講清楚:這是兩台實際部署的機器對跑,不是受控的硬體 A/B。兩邊 context 設定不同(256K 對 1M),不過上一篇量過這顆模型的 decode 幾乎不隨 context 變,所以這個差距我認為是真的。這只涵蓋單一 workload、單流、短輸入;流量型態一換,結論可能就不一樣。
收尾
DGX Spark 上裝這顆模型,真正要做的判斷只有一個:編譯的時候把 CUDA 路徑講死,然後用 ldd 確認它真的連對了。 其餘的不用管,因為 CPU 跟 GPU 共用同一塊記憶體。
而那個坑真正值得記的不是「CUDA 有兩套」,是它怎麼發作:編得過、載得進去、第一次推論才炸,而錯誤訊息指向 softmax。 下次再看到「載入正常、一跑就 CUDA error」,先去 ldd 一下,別急著怪模型。
這個系列的其他文章:
常見問題
- DGX Spark 上跑 DeepSeek-V4-Flash-0731 要不要調 expert offload?
- 不用。GB10 是統一記憶體,CPU 跟 GPU 共用同一塊 121 GiB,沒有「搬去顯卡」這個動作,所以 `-ncmoe` 這類旗標整組跳過。你只要確認 91GB 的權重加上 KV cache 塞得進那 121 GiB 就好,實測 process 吃 94,252 MiB。
- 為什麼模型載得進去,一推論就 CUDA error?
- 多半是編譯器跟 runtime 不同版,而這通常是自己的機器裝過多套 CUDA 才會有的問題——只裝一套的話不會遇到。我這台的 PATH 預設 `nvcc` 是 12.0、另外又裝了 13.2;CMake 用了我指定的編譯器,卻自己去系統目錄找到舊的 runtime。症狀是載入完全正常、第一次推論才丟 `SOFT_MAX failed / CUDA error: invalid argument`,看起來完全不像版本問題。
- DGX Spark 比一張二手 2080 Ti 快多少?
- 同一份 GGUF、同一個 llama.cpp、同一種量化下,我量到 DGX Spark decode 17.5–17.9 tok/s,單張改裝 2080 Ti 22G 配 EPYC 是 16.4–16.5 tok/s,差約 7%。DGX Spark 真正買到的不是速度,是「不用分堆」的省事和 121 GiB 的空間。
- context 該開 256K 還是 1M?
- 我 production 選 256K。1M 也載得起來(冷啟 416 秒),但 121 GiB 是 CPU 跟 GPU 共用的,長 context 把 KV 養大之後,留給系統的記憶體就會變緊。256K 載完還剩約 24 GiB,這個餘裕讓我晚上睡得著。
接著讀
- 2026-06-12[地端 LLM] 權重就是正義:284B 砍到 2-bit,還是比塞得下的小模型強
把 DeepSeek-V4-Flash(284B)壓到非對稱 Q2 才塞進 128GB 小盒子。聽起來像自殺式量化,但它只砍 routed experts、把高精度留在該留的層。實際當 agent 跑 280 輪零退化——權重夠大,2-bit 也壓不垮。
- 2026-06-12[地端 LLM] 把 15 tok/s 的 284B 當每天的 agent 大腦:DeepSeek-V4-Flash 怎麼設才舒服
一顆 284B、只有 15 tok/s 的模型,要拿來當每天的 agent 大腦,得先做點準備才用得舒服。server 跟 agent 框架兩邊各一組設定:--no-mmap 冷啟砍到 57 秒、KV disk cache 省一半 prefill、context_length 沒設對整個 session 會炸。
- 2026-06-12[地端 LLM] 第一次跑 Q2 就以為模型變笨了 —— 284B DeepSeek-V4-Flash 在 128GB 桌機,真兇是 parser 不認 DSML
DeepSeek-V4-Flash 是 284B 的 frontier 模型。我用 antirez 的 ds4 引擎 + 非對稱 Q2 在單台 GB10 跑起來,15.6 tok/s。本來以為 2-bit 量化讓它假裝呼叫工具,結果真兇是 runtime 沒接 DSML parser。
- 2026-07-10[本地 LLM] 怎麼判斷一個被吹爆的 LLM 優化,搬到你機器上是不是真的:讀原始碼、找天花板、跑一個實驗
本地 LLM 圈到處是被吹爆的優化——外掛 sparse-KV 壓縮器、「省 90% 記憶體」。多數搬到你自己的模型上就垮了。三個很便宜的動作判斷哪些是真的:讀原始碼、找真正的天花板、跑一個能定生死的實驗,全部拿 DeepSeek-V4-Flash 上那次 FlashMemory 調查來對照。
不想錯過新文章?
訂閱我確保不漏接!
隨時一鍵退訂。