Điểm chính?
DeepSeek V4 Flash chạy 2× DGX Spark với cấu hình TP=2, speculative decoding DSpark, KV cache NVFP4 và 1M context. Recipe chuẩn là MiaAI-Lab/DeepSeek-v4-Flash-DSpark-2x-DGX-Spark với image ghcr.io/anemll/dspark-vllm-gx10:0.1.1. Bốn hotfix bắt buộc: tắt earlyoom, spin-wait P-core (#79), assistant-final hotfix (#52), và tool-call truncation (#55). Tốc độ kỳ vọng: 62–83 tok/s cho một chat ≤128K, và ~160–190 tok/s tổng cho 6 chat ngắn — con số kỳ vọng từ README, cần đo lại khi máy về.
📊 Nguồn: README + CHANGELOG của recipe MiaAI-Lab (777★, commit 18/08/2026), nghiên cứu của 5ac trên 2× DGX Spark DeepSeek V4 Flash. Con số tốc độ là "kỳ vọng" từ Anemll, chưa phải số đo trên máy của 5ac.
Vì sao DeepSeek V4 Flash cần 2× DGX Spark
DeepSeek V4 Flash là model Mixture of Experts với khoảng 284 tỷ tham số. Một node DGX Spark có 128GB unified memory (CPU và GPU chia sẻ, CUDA thấy khoảng 121,7 GiB). Chạy model cỡ này trên một node — nhất là với 1M context thật và KV cache NVFP4 — là không khả thi: tổng weights và KV cache vượt bộ nhớ, và decode bị chặn trần bởi băng thông bộ nhớ ~273 GB/s thay vì bởi tính toán.
Hai node mở ra ba thứ cùng lúc. Một là tensor parallelism (TP=2): model được chia ngang hai máy, mỗi node giữ một phần weights và cùng tham gia suy luận. Hai là speculative decoding DSpark: dự đoán nhiều token rồi xác nhận một lần, thắng lớn trên phần cứng bị giới hạn bởi bandwidth như GB10. Ba là 1M context thật với text utilization 0.835 — tương đương khoảng 2,49 triệu token, đủ chứa bối cảnh của một doanh nghiệp lớn.
Nhưng hai node nghĩa là bài toán gấp đôi: đồng bộ, network fabric, NCCL, và thứ tự khởi động worker/head. Đây là chỗ một recipe đủ chín đáng giá hơn nhiều so với tự build.
Chốt recipe: MiaAI-Lab, không phải "tự build cho ngầu"
Sau khi rà soát hệ sinh thái open-source, chúng tôi chốt dùng recipe MiaAI-Lab/DeepSeek-v4-Flash-DSpark-2x-DGX-Spark (777★, commit mới nhất 18/08/2026, CI CPU-only validate mỗi push) làm base. Lý do không phải vì nó nổi tiếng, mà vì nó đã ship một loạt hotfix mà bản tự build sẽ rất tốn thời gian tự phát hiện.
Một lưu ý trung thực: chúng tôi chỉ dùng serving config của repo này, không dùng các model Hugging Face của MiaAI-Lab (Qwable/Gemmable). Có một discussion công khai tố rằng "Qwable" thực chất là bản quantized/dequantized của model gốc chứ không phải fine-tune thật — chúng tôi không lấy rủi ro đó. Config và code serving thì được đo thực tế, có ghi rõ credits, và là thứ đáng tin.
Image chuẩn: ghcr.io/anemll/dspark-vllm-gx10:0.1.1
Image chuẩn là ghcr.io/anemll/dspark-vllm-gx10:0.1.1 (từ Anemll/dspark-vllm-gx10), build riêng cho GB10 (ARM64/aarch64). Đây là điểm khác biệt quan trọng: GB10 không chạy được image x86 thông thường, và image này đã được recipe fork, audit và ship kèm hotfix mới nhất.
Đối với 5ac, image này tốt hơn image aidendle94/sparkrun-vllm-ds4-gb10 từng được ghi trong note mua 2× Spark — chúng tôi cập nhật quyết định deploy theo hướng này. Checkpoint dùng bản chính thức 0731 (ABLITERATED=0), tức không dùng weights bị abliterate.
Điểm mấu chốt: Với phần cứng 2 node, đừng cố tự build image. Image chuẩn của Anemll đã đóng gói đúng thư viện cho SM121 (không có native FP4 tensor cores, nên NVFP4 chạy qua flashinfer/triton backend). Tự build x86 hoặc dùng image sai kiến trúc sẽ tốn cả ngày để gỡ lỗi NCCL.
Cấu hình default profile
Cấu hình mặc định của recipe (bảng đầy đủ dưới đây) là điểm xuất phát an toàn nhất. Đừng chỉnh trước khi đo:
| Thành phần | Giá trị |
|---|---|
| Image | ghcr.io/anemll/dspark-vllm-gx10:0.1.1 |
| Checkpoint | official 0731 (ABLITERATED=0) |
| Context | MAX_MODEL_LEN=1048576 (1M) |
| Đồng thời | MAX_NUM_SEQS=6 · MAX_NUM_BATCHED_TOKENS=8192 |
| KV cache | nvfp4_ds_mla, text util 0.835 (~2,49M tokens) |
| Speculative | MTP_NUM_TOKENS=5 (≥ dspark_block_size) |
| Thinking | DEFAULT_THINKING=max · VLLM_USE_BREAKABLE_CUDAGRAPH=0 |
Hai giá trị đáng chú ý. --max-cudagraph-capture-size nên bằng MAX_NUM_SEQS × (MTP_NUM_TOKENS+1) = 36 (6×6). Và env mạng cho TP=2 gồm WORKER_HOST, MASTER_ADDR, NCCL_IB_HCA, NCCL_SOCKET_IFNAME, VLLM_HOST_IP, HF_CACHE. Recipe có hàm resolve_nccl_gid_indexes() tự resolve GID mỗi lần launch — tránh NCCL fail sau reboot. Dây nối giữa 2 node phải là cáp QSFP56 RoCE 200G DAC (Mellanox MCP1650-H00AE30 chẳng hạn), không phải Ethernet thường.
Bốn hotfix bắt buộc — khác biệt giữa "demo" và "production"
Đây là phần đáng giá nhất của recipe. Bốn hotfix dưới đây là điều biến một cụm "demo chạy" thành "production chạy được". Nếu bạn chạy agentic workload, bỏ sót bất kỳ cái nào sẽ trả giá bằng downtime hoặc transcript hỏng.
1. Tắt earlyoom trên cả 2 host. earlyoom giết process theo bộ nhớ — dưới deep-context load, nó sẽ giết vLLM ngay khi bộ nhớ cao, dù vLLM đang làm việc đúng. Đây là lỗi gián đoạn khó hiểu nhất và là thứ đầu tiên cần tắt.
2. Spin-wait P-core (#79). Giảm SpinCondition.busy_loop_s từ 1 xuống 0.002 trên TP=2. Bản cũ làm spin-wait chiếm trọn một Grace P-core, hao tài nguyên đắt nhất. Có opt-out DSPARK_SKIP_SPIN_WAIT_HOTFIX=1 nếu bạn cần hành vi cũ.
3. Assistant-final hotfix (#52/PR#53). Sửa agent-harness loop: khi request kết thúc bằng một assistant message, bản stock trả bare EOS và không có generation header → vòng lặp agent tạo các no-op turn và DSML ảo giác. Giờ là opt-in DSPARK_ENABLE_ASSISTANT_FINAL_HOTFIX=1 (default 0 = stock), fail-closed (restore bytes nếu fail) và idempotent.
4. Tool-call truncation (#55). Trước đây, khi max_tokens cắt giữa một tool call, model báo finish_reason="length" kèm "tool_calls" + JSON dở — transcript bị 400 poison. Hotfix này ngăn chặn đúng tình huống đó. Lưu ý giới hạn protocol: streaming args vẫn append-only.
Điểm mấu chốt: Các hotfix #21/#26/#27/#43 luôn chạy và không bị bỏ qua bởi DSPARK_SKIP_HOTFIX; #22 là riêng biệt. Và nhớ: env VLLM_DSPARK_* là no-op trên Anemll 0.1.1 (chỉ có hiệu lực khi đổi sang image Stage-C).
Ngoài bốn cái bắt buộc, recipe còn ship vài hotfix hữu ích khác: start after reboot (#72) — container đã up thì trả exit 3 thay vì exit 1, nên systemd cấu hình SuccessExitStatus=3 để tránh retry storm; RULER-lite context (#81) — bulk-pad đúng 32k/262k cells (trước cap ~4.8k dù exit 0); thinking budget (#31/#48) — 2 Triton kernel hard-cap reasoning, đưa tốc độ từ 37.2 lên 59.3 tok/s, bỏ hẳn "vực thẳm" ~4.5 tok/s.
Ops scripts và systemd sau reboot
Recipe đóng gói đầy đủ script vận hành: start- / stop- / status- / logs- / smoke-*.sh, chạy theo thứ tự worker-first, head sau. Điều này quan trọng với TP=2: node worker phải sẵn sàng trước khi head launch, nếu không NCCL rendezvous sẽ treo.
Cho production, gắn các script vào systemd để cụm tự khởi động lại an toàn sau reboot. Vì hotfix #72 đã trả exit 3 khi container đã up, cấu hình SuccessExitStatus=3 để systemd không retry liên tục. Cùng với resolve_nccl_gid_indexes() tự resolve GID, cụm của bạn trở nên sống sót qua reboot mà không cần thao tác tay.
Nếu cần thêm khả năng, recipe có sidecar tùy chọn ENABLE_VL_SIDECAR=1 (Qwen3-VL trên :8889 + MCP) và ENABLE_VLLM_GB10_PATCH=1 (--quantization modelopt_gb10_hybrid, default OFF).
Responses API live verifier — 4 cổng kiểm tra
Điều làm recipe này khác bản tự build: script verify-responses-api-live.py kiểm tra trực tiếp 4 cổng của Responses API:
- Text/SSE — streaming phản hồi đúng định dạng.
- Stateful tool continuation — agent gọi tool rồi tiếp tục đúng context (cần
VLLM_ENABLE_RESPONSES_API_STORE=1). - Strict JSON schema — output khớp schema khai báo.
- Reasoning + multi-turn prefix reuse + disconnect cleanup — hành vi dài hơi và dọn dẹp khi client ngắt kết nối.
Chạy verifier này sau mỗi lần deploy là cách nhanh nhất để biết "cụm còn sống đúng nghĩa" hay chỉ "cụm còn lên mạng". Với workload agentic, 4 cổng này là thứ bạn cần tin trước khi đưa agent vào sản xuất.
Tuning áp dụng từ benchmark GB10
Khi cụm chạy ổn định, đây là các tuning đã được đo trên GB10 thật (từ repo Qwen3.8-27B-SGLang và benchmark nội bộ của 5ac), áp dụng được cho triết lý vận hành DeepSeek V4 Flash:
- GDN state bf16 thay vì float32 — float32 chậm khoảng 3%.
- Spec steps 3/1/4 là peak. Sweep 2→6 cho 12,8 / 17,2 / 16,8 / 16,3 / 15,8 tok/s thinking; 3/1/4 đỉnh nhất.
- Pin 10 lõi Cortex-X5 (
--cpuset-cpus 5-9,15-19) → +2–7% decode, vì scheduler/tokenizer không float lên A725 2.8GHz. - Mem 0.90 · chunked prefill 8192 · KV cache FP8 (
fp8_e4m3) cho model dùng FP8.
Một giới hạn cần nhớ: DSpark không dùng YaRN / context > 262K (giới hạn bản build). Nếu bạn thực sự cần 1M context thì chính là cấu hình NVFP4 + MTP của recipe này đang làm — đó là lý do DeepSeek V4 Flash trên 2× Spark không bị ràng buộc giới hạn đó.
FAQ
Recipe này dùng được cho 1× DGX Spark không?
Không cho DeepSeek V4 Flash. Model này cần TP=2 với 1M context và NVFP4 — 2× Spark là cấu hình tối thiểu khả thi. Nếu chỉ có 1 node, nên xem model nhẹ hơn (như Qwen3.8-27B FP8) chạy vừa 128GB.
Con số 62–83 tok/s là đo trên máy của 5ac không?
Chưa. Đó là con số kỳ vọng từ README Anemll, chưa phải số đo trên phần cứng của 5ac. Chúng tôi sẽ đo lại n=5 khi máy về và công bố trên blog. Trong bài này, mọi con số ghi "kỳ vọng" đều theo quy ước đó.
Tôi có cần cáp RoCE đặc biệt giữa 2 node không?
Có. Cáp QSFP56 RoCE 200G DAC là bắt buộc để TP=2 hoạt động đúng tốc độ (ví dụ NVIDIA/Mellanox MCP1650-H00AE30). Chạy qua Ethernet thường sẽ làm NCCL chậm và cụm không đạt tốc độ kỳ vọng.
Chạy agentic workload có cần bật assistant-final hotfix không?
Có, gần như bắt buộc. Nếu request kết thúc bằng assistant message, bản stock (default 0) sẽ tạo no-op turns và DSML ảo giác. Bật DSPARK_ENABLE_ASSISTANT_FINAL_HOTFIX=1 để agent-harness loop chạy đúng.
Kết luận
Deploy DeepSeek V4 Flash trên 2× DGX Spark không phải là chuyện mua máy về rồi chạy một lệnh. Nó là chuyện chọn đúng recipe, dùng đúng image, áp dụng đủ hotfix, và tin vào một verifier đo thật thay vì "thấy nó trả lời là được".
Với 5ac, recipe MiaAI-Lab/Anemll là điểm xuất phát vững nhất chúng tôi tìm được trong hệ sinh thái open-source: ops scripts đầy đủ, hotfix fail-closed, và Responses API verifier. Chúng tôi fork, audit và sẽ đo lại trên chính phần cứng của mình — vì mọi recipe trong repo 5ac đều chạy thật, không phải slide.