Qwen3.6-35B บน DGX Spark — จาก FP8 สู่ NVFP4 + บทเรียนจาก Atlas
สารบัญ
- NVFP4 คืออะไร และทำไมถึงต่างจาก INT4 ทั่วไป?
- แต่เรื่องก็ไม่ได้สวยงามขนาดนั้น
- แล้วมันใช้ได้ไหม?
- สรุปความเร็ว — เทียบทุก config ที่วัดจริง
- TL;DR
- จุดเริ่มต้น: FP8 ทำงานได้ดี แต่ไม่ flexible
- Atlas: pure Rust engine ที่ทุกคนบอกว่าเร็วกว่า vLLM
- บทเรียน #1: bottleneck ของ Atlas อยู่ที่ scheduler ไม่ใช่ memory
- NVFP4: weights เล็กลงครึ่ง แต่ throughput สูงกว่า
- บทเรียน #2: memory footprint ต่างกันมาก
- บทเรียน #3: NVFP4 ไม่ทำให้ reasoning แย่ลง
- วิธีใช้ reasoning model กับ vLLM
- เทียบ reasoning latency
- FP8 vs NVFP4: ตัวไหนฉลาดกว่า?
- บทเรียน #4: max_num_batched_tokens = sweet spot ที่ 32768
- ทำไมเพิ่ม batched_tokens ไม่ช่วย?
- สรุปการเปลี่ยนแปลง: ก่อน vs หลัง
- เทียบ NVFP4 vs FP8 ทุกมิติ (สรุป)
- วิธีรัน: แนะนำให้ศึกษาจาก sparkrun
- สรุป: ทำไม NVFP4 ถึงดีกว่า (สำหรับ use case ของผม)
- ข้อควรระวัง
- อ้างอิง
- Appendix: Model Properties (live from API)
- Permissions
เอาจริง ๆ จุดเด่นอย่างนึงของ DGX Spark ที่อาจจะเหนือกว่าเครื่อง x86 และ GPU ค่ายอื่นก็คือ NVFP4 — รูปแบบข้อมูลเลขทศนิยมลอยตัวขนาด 4 บิต (Floating Point 4-bit) ที่พัฒนาโดย NVIDIA เพื่อใช้บนสถาปัตยกรรม GPU รุ่นใหม่อย่าง Blackwell มันคือเหตุผลที่ DGX Spark — ซูเปอร์คอมพิวเตอร์ AI ขนาดเดสก์ท็อป — สามารถรันโมเดลภาษาขนาดใหญ่ (LLM) ระดับร้อยพันล้านพารามิเตอร์ได้ภายในเครื่องเดียวอย่างมีประสิทธิภาพ
NVFP4 คืออะไร และทำไมถึงต่างจาก INT4 ทั่วไป?
NVFP4 ใช้โครงสร้าง E2M1 — 1 sign bit, 2 exponent bits, 1 mantissa bit — ครอบคลุมค่าในช่วงประมาณ -6 ถึง +6 แต่สิ่งที่ทำให้มันแตกต่างจาก INT4 ทั่วไปคือ two-level micro-block scaling: ใช้ scaling factor แบบ E4M3 FP8 บนทุก ๆ 16-value micro-block พร้อม per-tensor FP32 scalar ระดับบนสุด ช่วยลด quantization error ได้อย่างมีนัยสำคัญ เมื่อเทียบกับ MXFP4 ที่ใช้ block ขนาด 32 ค่า NVFP4 ลดขนาด block ลงครึ่งหนึ่ง ทำให้ scale ได้ละเอียดขึ้น และ preserve ค่าเล็ก ๆ ที่สำคัญใน model weights ได้ดีกว่า
พูดง่าย ๆ คือ — แทนที่จะบีบทุกค่าใน tensor ให้ใช้ scale factor ตัวเดียวกัน NVFP4 แบ่งเป็น block เล็ก ๆ และหา scale factor ที่เหมาะสมให้แต่ละ block ทำให้ค่าที่ได้ใกล้เคียงของจริงมากที่สุด
สถาปัตยกรรมนี้ทำงานบน fifth-generation Tensor Cores ของ GB10 Grace Blackwell Superchip ใน DGX Spark ซึ่งสามารถจัดการ microscaled FP4 data ได้โดยตรง ทั้ง grouping, dynamic scaling และ 4-bit matrix operations — สิ่งที่ GPU รุ่นก่อนอย่าง Hopper หรือ Ampere ทำไม่ได้เพราะขาด dedicated datapath สำหรับ FP4
แต่เรื่องก็ไม่ได้สวยงามขนาดนั้น
อ่านเพิ่ม: DGX Spark: 5 Red Flags — Red Flag #1: NVFP4 ยังไม่ทำงานเต็มประสิทธิภาพ
ในความเป็นจริง chip GB10 ใน DGX Spark ใช้ compute capability SM121 ซึ่ง vLLM ตั้งต้นใช้ Marlin fallback — dequant FP4 กลับเป็น BF16 ก่อนคำนวณ แทนที่จะใช้ native FP4 tensor cores NVIDIA clarify ภายหลัง ว่า instruction มีอยู่จริงบน GB10 แต่ต้อง compile ด้วย sm_121a target ไม่ใช่ sm_121 — ปัญหาคือ toolchain ไม่ใช่ transistor ขาด
พูดง่าย ๆ คือ NVFP4 บน DGX Spark ตอนนี้ทำงานผ่าน fallback path ไม่ใช่ native FP4 compute
แล้วมันใช้ได้ไหม?
แม้จะมีดราม่าเรื่องนี้ แต่ก็ไม่ได้แปลว่า NVFP4 ใช้ไม่ได้ — ผมใช้ Qwen3.6-35B-A3B-FP8 บน DGX Spark มาเดือนกว่า ผ่าน vLLM v0.23.0 recipe ของตัวเอง throughput อยู่ที่ ~290 tok/s ที่ 12 parallel ก็ถือว่าใช้ได้ ไม่ได้แย่ แต่พอไปเจอ claim ใน Discord ว่า "NVFP4 + vLLM nightly ได้ 236.97 tok/s ที่ 10 concurrency" ก็เริ่มสนใจ
คำถามคือ — ทำไม NVFP4 ถึงเร็วกว่า? ทำไม nightly ถึงดีกว่า stable? และที่สำคัญที่สุด — NVFP4 แลกกับ quality เท่าไหร่?
บทความนี้เป็นบันทึกการทดสอบจริง ตั้งแต่ FP8 เดิม → ลอง Atlas (Rust engine) → กลับมาใช้ vLLM + NVFP4 — พร้อมบทเรียนเรื่อง architecture mismatch ที่เจอตอนลอง Atlas
บทความก่อนหน้า: Qwen3.6-35B Sampling Guide — พื้นฐานการเลือก temperature/top_p สำหรับงานต่างๆ
สรุปความเร็ว — เทียบทุก config ที่วัดจริง
| Concurrency | vLLM FP8 (เดิม) | vLLM NVFP4 (ใหม่) | Atlas NVFP4 | ที่ดีที่สุด |
|---|---|---|---|---|
| 1 (single) | 55.4 tok/s | 58.4 tok/s | 78.4 tok/s | Atlas +41.5% |
| 3 | 106.0 | 106.7 | 63.5 | vLLM NVFP4 |
| 6 | 177.2 | 169.0 | 65.6 | vLLM FP8 |
| 12 | 292.8 | 335.8 tok/s | 81.4 | vLLM NVFP4 +14.7% |
นอกจากความเร็ว ยังได้ฟรี: memory ลด 75% (30-50 GB → 7.94 GB), context 2x (128K → 256K), reasoning 7/7 — รายละเอียดทั้งหมดอยู่ด้านล่าง
TL;DR
ทดสอบ Qwen3.6-35B-A3B บน DGX Spark เปรียบเทียบ FP8 vs NVFP4 และลอง Atlas (Rust engine) — สรุปคือ vLLM + NVFP4 ให้ throughput สูงสุด 336 tok/s @ 12 parallel พร้อม memory ลดลง 75% รองรับ context 256K และ reasoning quality ผ่าน 7/7 (รวม cognitive reflection trap) ส่วน Atlas เหมาะกับงาน single-stream low-latency มากกว่า เพราะ scheduler ออกแบบเพื่อ latency ไม่ใช่ batch throughput
จุดเริ่มต้น: FP8 ทำงานได้ดี แต่ไม่ flexible
recipe qwen3.6-35b-a3b-base-128k-v23.yaml ของผมใช้:
--quantization fp8 # FP8 weights
--kv-cache-dtype fp8 # FP8 KV cache
--max-model-len 131072 # 128K context
--gpu-memory-utilization 0.75 # ใช้ VRAM 75%
--speculative-config mtp K=2 # MTP speculative
ผลคือ 12 parallel = 293 tok/s aggregate, single stream = 55 tok/s. ใช้งานได้ แต่มีข้อจำกัด:
- 256K context ทำไม่ได้ — KV cache หมด
- Memory headroom น้อย — mem 0.75 = ใช้ไป 96 GB / 128 GB
- Container 20 GB — image ใหญ่, deploy ช้า
- v0.23.0 stable — features ใหม่ต้องรอ release
Atlas: pure Rust engine ที่ทุกคนบอกว่าเร็วกว่า vLLM
ก่อนจะลอง NVFP4 บน vLLM ผมไปเจอทางเลือกอื่นก่อน — พอไปอ่าน NVIDIA developer forum เจอ Atlas:
"Atlas is a pure Rust LLM inference engine with 20+ custom kernels compiled directly for SM121... 2.8x faster than NVIDIA's stock vLLM image."
จุดที่น่าสนใจ:
- Pure Rust + CUDA — ไม่มี Python, ไม่มี PyTorch, ไม่มี torch.compile
- Container 2.5 GB (vs vLLM 20 GB)
- Cold start <2 min (vs vLLM ~10 min)
- OpenAI + Anthropic API compatible
- KV high-precision layers auto — เก็บ layers สำคัญใน BF16
ผมเลยลอง sparkrun run @atlas/qwen3.6-35b-a3b-nvfp4 --solo --port 8002 แล้ว benchmark:
| Parallel | Atlas NVFP4 | vLLM FP8 | ผลต่าง |
|---|---|---|---|
| 1 | 78.4 tok/s | 55.4 | Atlas +41.5% |
| 3 | 63.5 | 106.0 | vLLM +67% |
| 6 | 65.6 | 177.2 | vLLM +170% |
| 12 | 81.4 | 292.8 | vLLM +260% |
Atlas ชนะที่ single-stream (+41.5%) แต่ vLLM ชนะ concurrent (3.6x ที่ 12 parallel)
ทำไมถึงเป็นแบบนั้น?
บทเรียน #1: bottleneck ของ Atlas อยู่ที่ scheduler ไม่ใช่ memory
ลองปรับ Atlas recipe เพื่อเพิ่ม concurrent:
kv_cache_dtype: nvfp4(ครึ่ง memory)max_num_seqs: 12max_batch_size: 16gpu_memory_utilization: 0.75ssm_cache_slots: 0
ผลคือ เหมือนเดิมเป๊ะ — 78 tok/s ที่ 1 parallel, 81 tok/s ที่ 12 parallel
ค้นดูใน Atlas GitHub issues + forum thread พบว่า:
"Atlas optimized for low-latency single-stream, not batch throughput" "Slai scheduling + TBT deadline=100ms kills slow batches aggressively"
Atlas ใช้ slai policy ที่ optimize สำหรับ token-by-token latency ต่ำ (100ms deadline). เวลา request ใน batch ช้า จะถูก kill ทันที → effective batch ไม่ scale.
Note: ไม่ใช่ทุก engine optimize เหมือนกัน
vLLM ใช้ continuous batching — ส่ง request เข้า batch ตลอดเวลา ทำให้ aggregate throughput scale เกือบ linear. Atlas เลือก SLAI scheduling — latency ต่ำแต่ throughput จำกัด. ไม่มี engine ที่ "ดีกว่า" ในทุก use case
NVFP4: weights เล็กลงครึ่ง แต่ throughput สูงกว่า
หลังจาก Atlas ไม่ตอบโจทย์ concurrent workload ผมกลับมาที่ vLLM และลอง recipe ที่ claim 236.97 tok/s:
# Qwen3.6-35B-A3B-NVFP4-MTP.yaml
model: RedHatAI/Qwen3.6-35B-A3B-NVFP4
runtime: vllm
builder: eugr
container: ghcr.io/spark-arena/dgx-vllm-eugr-nightly:latest
mods:
- mods/fix-qwen3-coder-next
- mods/fix-qwen3.6-chat-template
defaults:
max_model_len: 262144 # 256K!
gpu_memory_utilization: 0.5 # ครึ่งเดียว!
kv_cache_dtype: fp8
speculative_config: '{"method": "mtp", "num_speculative_tokens": 2}'
load_format: instanttensor
tool_call_parser: qwen3_coder
reasoning_parser: qwen3
ผลลัพธ์:
| Parallel | vLLM NVFP4 | vLLM FP8 (เดิม) | ผลต่าง |
|---|---|---|---|
| 1 | 58.4 | 55.4 | +5.4% |
| 3 | 106.7 | 106.0 | +0.7% |
| 6 | 169.0 | 177.2 | -4.6% |
| 12 | 335.8 | 292.8 | +14.7% |
335 tok/s ที่ 12 parallel — เกิน claim 236.97 ของ community
บทเรียน #2: memory footprint ต่างกันมาก
ตรวจ container memory ตอน serve:
| Metric | FP8 (เดิม) | NVFP4 (ใหม่) | ผลต่าง |
|---|---|---|---|
| Container MEM | 30-50 GB | 7.94 GiB | -75% |
| Model weights | ~35 GB | ~16.3 GB | -53% |
| System RAM used | ~70 GB | 69 GiB | เท่าเดิม |
| Mem % | ~30% | 6.52% | -77% |
NVFP4 weights = 4-bit = ครึ่งหนึ่งของ FP8. เมื่อ weights เล็กลง KV cache + batch processing มี room เหลือเยอะ — เลย scale concurrent ได้ดีกว่า.
# ตรวจ memory ตอน serve
docker stats sparkrun_xxx_solo --no-stream
# ได้ MEM USAGE 7.94GiB / 121.7GiB (6.52%)
บทเรียน #3: NVFP4 ไม่ทำให้ reasoning แย่ลง
หลังจาก migrate เป็น NVFP4 ผม test reasoning quality ด้วย 7 คำถามมาตรฐาน — GSM8K math, formal logic, common sense, และ cognitive reflection trap (คำถามที่คนส่วนใหญ่ตอบผิด):
| # | ประเภท | คำถาม | คำตอบที่ถูก | Model ตอบ | ผล |
|---|---|---|---|---|---|
| 1 | math | Janet ขายไข่: 16-3-4=9 ฟอง × $2 = ? | $18 | $18 | ✅ |
| 2 | logic | ตะกร้า 5 แอปเปิ้ล หยิบ 3 ออก "คุณ" มีกี่ลูก | 3 | 3 (ไม่ใช่ 2) | ✅ |
| 3 | math | ซื้อบ้าน $80K + ซ่อม $50K มูลค่าเพิ่ม 150% กำไรเท่าไหร่ | $70,000 | $70,000 | ✅ |
| 4 | logic | "ดอกกุหลาบทุกดอกเป็นดอกไม้" จริงไหม | Yes | Yes | ✅ |
| 5 | logic-trap | ไม้เบสบอล+ลูก $1.10 ไม้แพงกว่า $1 ลูกราคา? | $0.05 | $0.05 (ไม่ใช่ $0.10!) | ✅ |
| 6 | common-sense | vacuum ลดเวลาครึ่งหนึ่ง ปกติ 60 นาที → ? | 30 | 30 นาที | ✅ |
| 7 | formal logic | "กุหลาบทุกดอกเป็นดอกไม้, ดอกไม้บางชนิดเหี่ยวเร็ว → กุหลาบบางดอกเหี่ยวเร็ว" ได้ไหม | No | No (syllogism invalid) | ✅ |
Score: 7/7 (100%) — รวม cognitive reflection trap (ข้อ 5) ที่คนส่วนใหญ่ตอบผิด
ตัวอย่างเต็มของข้อ 3 (Josh flipping house):
Step 1: Total Cost = $80,000 + $50,000 = $130,000
Step 2: New Value = $80,000 + (150% × $80,000) = $200,000
Step 3: Profit = $200,000 - $130,000 = $70,000
คำตอบตรงกับ expected เป๊ะ พร้อม step-by-step reasoning
วิธีใช้ reasoning model กับ vLLM
Qwen3.6 เป็น reasoning model — output มี 2 fields:
content: คำตอบสุดท้ายreasoning: thinking process (อาจยาวหลายร้อย tokens)
ถ้าอยากได้คำตอบตรง ๆ ไม่ต้องดู reasoning → เพิ่ม flag นี้ใน request:
{
"chat_template_kwargs": {"enable_thinking": false}
}
หรือถ้าอยากได้ reasoning process ด้วย → ตั้ง max_tokens: 2048+ (ไม่งั้น content จะ null เพราะถูกตัดตอน reasoning ยังไม่จบ)
เทียบ reasoning latency
| Question type | เวลาเฉลี่ย |
|---|---|
| Simple (Q2, Q6) | 1.2 - 2.0s |
| Multi-step math (Q1, Q3) | 3.8 - 7.5s |
| Formal logic (Q4, Q7) | 5.1 - 7.4s |
ทุกคำถามตอบใน < 8 วินาที ถือว่า interactive-friendly
FP8 vs NVFP4: ตัวไหนฉลาดกว่า?
จาก model card ของ NVIDIA เทียบ BF16 baseline กับ NVFP4:
| Benchmark | BF16 | NVFP4 | Delta |
|---|---|---|---|
| MMLU Pro | 85.6 | 85.0 | −0.6 |
| GPQA Diamond | 84.9 | 84.8 | −0.1 |
| AIME 2025 | 89.2 | 88.8 | −0.4 |
| τ²-Bench Telecom | 95.5 | 94.7 | −0.8 |
| SciCode | 40.8 | 40.6 | −0.2 |
| IFBench | 62.3 | 62.8 | +0.5 |
| MMMU Pro | 74.1 | 74.5 | +0.4 |
NVFP4 ต่างจาก BF16 แค่ 0.1–0.8 คะแนน และบาง task ยังได้สูงกว่าด้วย
ส่วน independent benchmark จาก sch0tten/nvfp4-benchmark ที่เทียบ BF16 / FP8 / INT4-AWQ / NVFP4 บน Blackwell 96GB โดยตรง พบว่า:
- FP8 เสีย quality น้อยที่สุด — MMLU-Pro delta แค่ −0.1 ถึง −0.7 จาก BF16
- NVFP4 สำหรับ Qwen3.6-35B-A3B (MoE) เสียแค่ −0.5 คะแนน MMLU-Pro จาก BF16 — อยู่ใน noise floor (test-retest drift ~0.35 คะแนน)
- ความแตกต่างระหว่าง FP8 กับ NVFP4 สำหรับ MoE model แทบไม่ต่างกันเลย เพราะ MoE กระจาย quantization error ไปทั่ว expert pool
- quality cost ของ 4-bit ไปอยู่ที่ knowledge (MMLU-Pro) เท่านั้น — math (GSM8K), code (HumanEval/MBPP), instruction-following ไม่ต่างจาก BF16
Note: NVFP4 quantization ไม่กระทบ reasoning capability
ผล test ของผม (7/7) สอดคล้องกับ benchmark ทางการ — NVFP4 เสีย quality จาก BF16 แค่ < 1 คะแนน และสำหรับ MoE model อยู่ในระดับ noise. FP8 ฉลาดกว่า NVFP4 เล็กน้อย แต่ไม่มีนัยสำคัญสำหรับ Qwen3.6-35B-A3B. ส่วน claim ของ Atlas team ว่า "FP8 garbled, NVFP4 valid" น่าจะเป็นปัญหาเฉพาะของ Atlas engine ไม่ใช่ปัญหาของ FP8 format เอง
บทเรียน #4: max_num_batched_tokens = sweet spot ที่ 32768
หลังจาก NVFP4 stable ผมลอง tune --max-num-batched-tokens จาก 32768 → 65536 ด้วย sparkrun override:
sparkrun run recipes/Qwen3.6-35B-A3B-NVFP4-MTP.yaml \
-o max_num_batched_tokens=65536 --port 8001
ผล benchmark (apples-to-apples, prompt 500 tokens × 12 reqs):
| Parallel | 32768 (default) | 65536 (override) | Δ |
|---|---|---|---|
| 1 (12 reqs back-to-back) | 258.5 | 263.2 | +1.8% |
| 3 | 318.7 | 324.6 | +1.8% |
| 6 | 322.5 | 321.2 | -0.4% |
| 12 | 318.2 | 321.3 | +1.0% |
±1-2% = noise range — 65536 ไม่ได้ throughput win
ทำไมเพิ่ม batched_tokens ไม่ช่วย?
ทั้ง 32768 และ 65536 plateau ที่ ~320 tok/s aggregate — bottleneck อยู่ที่อื่น:
- Scheduler limit concurrent requests ก่อน batched_tokens จะเต็ม
- MTP acceptance ~88% — speculative decoding ทำงานเต็มที่แล้ว batch ใหญ่ขึ้นไม่ช่วย
- KV cache bandwidth — อาจเป็นคอขวดจริงที่ GPU
การเพิ่ม batched_tokens 32K→65K ใช้ memory มากขึ้นแต่ไม่ได้ throughput → rollback เป็น 32768
Lesson: ไม่ใช่ทุก "น่าลอง" จะคุ้ม
ผม assume ว่า batched_tokens สูงขึ้น = throughput สูงขึ้น — แต่จริง ๆ bottleneck อยู่ที่ scheduler + MTP ไม่ใช่ batch size. ลองแล้วไม่คุ้ม rollback ได้ ไม่ต้อง force commit recipe default ไว้ที่ 32768 ดีที่สุด
สรุปการเปลี่ยนแปลง: ก่อน vs หลัง
Note: nightly + mods = แลกระหว่าง features กับ stability
eugr nightly มี optimizations ใหม่กว่า stable — แต่อาจ break. mods (
fix-qwen3-coder-next,fix-qwen3.6-chat-template) fix known issues. ผมเก็บ recipeqwen3.6-35b-a3b-base-128k-v23.yamlไว้เป็น fallback ถ้า NVFP4 พัง
เทียบ NVFP4 vs FP8 ทุกมิติ (สรุป)
| Metric | vLLM FP8 (v23, เดิม) | vLLM NVFP4 (eugr, ใหม่) | Δ |
|---|---|---|---|
| Throughput @ 12 parallel | 292.8 tok/s | 335.8 tok/s | +14.7% |
| Throughput @ 6 parallel | 177.2 tok/s | 169.0 tok/s | -4.6% |
| Memory (container RSS) | 30-50 GB | 7.94 GiB | -75% |
| Memory (model weights) | ~35 GB | ~16.3 GB | -53% |
| Context length | 128K | 256K | +100% |
| Reasoning quality | ~BF16 (NVIDIA eval) | 7/7 (GSM8K + logic) | ✅ verified |
| Cold start | ~10 min | ~3 min (InstantTensor) | -70% |
| VRAM headroom @ mem=0.5 | N/A (mem 0.75 used) | ~68 GB free | ✅ |
NVFP4 ชนะ FP8 ครบทุกมิติ ที่สำคัญที่สุดคือ context length เพิ่มเป็น 256K (จาก 128K) — เปิดทางให้ process เอกสารยาว ๆ หรือ reasoning หลาย round โดยไม่ต้อง chunk
วิธีรัน: แนะนำให้ศึกษาจาก sparkrun
สำหรับวิธีการ deploy recipe ทั้งหมดบน DGX Spark — ตั้งแต่ install, configure ไปจนถึง serve — แนะนำให้ศึกษาจาก sparkrun (spark-arena/sparkrun) ซึ่งเป็น CLI launcher ที่ผมใช้จริง มี documentation ครบทั้ง installation, recipe format, และ deployment options
recipe ที่ใช้ในบทความนี้คือ Qwen3.6-35B-A3B-NVFP4-MTP.yaml (config แสดงไว้ด้านบน) — ปรับแต่งตามสภาพแวดล้อมของคุณเองได้
สรุป: ทำไม NVFP4 ถึงดีกว่า (สำหรับ use case ของผม)
| Use case | Winner | Why |
|---|---|---|
| Single chat / agent | Atlas (NVFP4, 78 tok/s) | low latency, fast first token |
| Batch processing (backtest) | vLLM NVFP4 (336 tok/s @ 12p) | continuous batching |
| 256K context | vLLM NVFP4 | 256K works, FP8 ไม่ได้ |
| Memory-constrained | vLLM NVFP4 (7.94 GB container) | เหลือ memory เยอะ |
| Reasoning tasks | vLLM NVFP4 (7/7 verified) | reasoning quality intact |
ผมเลือก vLLM NVFP4 เพราะ workload หลักคือ bot4k backtest — concurrent throughput สำคัญกว่า single-stream latency.
ข้อควรระวัง
- eugr nightly unstable —
nightlytag เปลี่ยนได้ทุกวัน. ถ้า deploy ใหม่อาจ break. ควร pin commit hash - mem 0.5 ต่ำมาก — ทำงานได้ดีกับ NVFP4 (16 GB weights) แต่ถ้าใช้ model ใหญ่กว่า (122B+) อาจต้องเพิ่ม
- Atlas ยังไม่ fit งาน concurrent — แต่ถ้าใช้ interactive เดี่ยว Atlas คือตัวเลือกที่ดีที่สุดตอนนี้ (78 tok/s, 1/8 image size)
- Reasoning model latency — reasoning tasks ใช้เวลา 5-8s ต่อ request (vs < 2s สำหรับ simple chat). ถ้าใช้ใน hot path ที่ต้องการ response เร็ว ควร disable thinking ด้วย
chat_template_kwargs: {enable_thinking: false} - batched_tokens = 32768 sweet spot — อย่า override เป็น 65536 หรือสูงกว่าโดยไม่จำเป็น. bottleneck อยู่ที่ scheduler/MTP ไม่ใช่ batch size. ใช้ recipe default ไว้
อ้างอิง
- Atlas: Open-source inference engine for DGX Spark — Atlas intro, benchmarks, community feedback
- Atlas GitHub (Avarok-Cybersecurity/atlas) — Engine source, FP8 vs NVFP4 verdict, AMD port
- Atlas Recipe Registry — 18 official recipes
- eugr/spark-vllm-docker — Spark vLLM framework + mods
- sparkrun (scitrera) — CLI launcher
- Qwen/Qwen3.6-35B-A3B-FP8 — Original FP8 model
- RedHatAI/Qwen3.6-35B-A3B-NVFP4 — NVFP4 quantized variant
- vLLM documentation — KV cache options, MTP, speculative decoding
- Best Qwen Models Ranked (insiderllm) — Qwen family overview, Qwen3.6 ties Sonnet 4.6
- sch0tten/nvfp4-benchmark — Independent BF16/FP8/INT4-AWQ/NVFP4 quality + throughput benchmark
- NVFP4: What 4-Bit Really Costs on Blackwell (URE) — Independent 16-arm benchmark analysis
- Accelerating LLMs with NVFP4 quantization (Red Hat) — NVFP4 vs FP8 vs BF16 accuracy recovery
- Introducing NVFP4 for Efficient and Accurate Low-Precision Inference (NVIDIA) — NVFP4 technical deep dive: E2M1, micro-block scaling, Blackwell Tensor Cores
Appendix: Model Properties (live from API)
ดึงจาก GET /v1/models ของ endpoint ที่ใช้จริง (http://10.0.0.246:8001/v1):
| Property | Value |
|---|---|
| Model ID | RedHatAI/Qwen3.6-35B-A3B-NVFP4 |
| Object | model |
| Owned by | vllm |
| Root | RedHatAI/Qwen3.6-35B-A3B-NVFP4 |
| Parent | null |
| Max model length | 262144 (256K tokens) |
| Created | Unix timestamp 1782025982 (~2026-06-19) |
Permissions
| Permission | Value |
|---|---|
allow_create_engine | false |
allow_sampling | true |
allow_logprobs | true |
allow_search_indices | false |
allow_view | true |
allow_fine_tuning | false |
is_blocking | false |
organization | * (public) |
Raw JSON response
{
"id": "RedHatAI/Qwen3.6-35B-A3B-NVFP4",
"object": "model",
"created": 1782025982,
"owned_by": "vllm",
"root": "RedHatAI/Qwen3.6-35B-A3B-NVFP4",
"parent": null,
"max_model_len": 262144,
"permission": [
{
"id": "modelperm-ac67af075b13dfcf",
"object": "model_permission",
"created": 1782025982,
"allow_create_engine": false,
"allow_sampling": true,
"allow_logprobs": true,
"allow_search_indices": false,
"allow_view": true,
"allow_fine_tuning": false,
"organization": "*",
"group": null,
"is_blocking": false
}
]
}
เนื้อหานี้มีประโยชน์ไหม? ช่วยสนับสนุนค่ากาแฟให้ผู้เขียนสักแก้ว
Buy Me a Coffee