122B-os modell egy DGX Sparkon: élesben mérve
Qwen3.5-122B-A10B NVFP4 single Sparkon — meddig bírja, hol törik el, és érdemes-e DocAI-be tenni
A februári Qwen3.5-122B-A10B kiadás óta a community thread-ekben csordogált a kérdés: megéri a 122B paraméteres MoE-t single Sparkon futtatni, vagy maradjunk a 35B-A3B-nél? A válasz három hónapig bizonytalan volt — vagy senki sem kapcsolta össze pontosan, mit változtat a vLLM build, a checkpoint, az MTP, az NVFP4 quantization és a gpu_memory_utilization flag.
Most összekapcsoltam.
Ez az írás dokumentálja, mit néz ki egy 76 GB-os modell betöltése a 121 GiB unified memóriába egy GB10 chipen, mennyit ad az MTP különböző workload-okon (rövidülne: nem ugyanannyit), miért fogja a vLLM autoselect-elni a FLASHINFER_CUTLASS MoE backendet — annak ellenére, hogy a régi thread-ekben mindenki azt írta, hogy SM121-en bukni fog, és mit jelent pontosan az hogy „a Spark bírja a 4 párhuzamos 100K-s kérést”.
Eddigi cikkek után ez egy single-Spark mérés. Nincs cluster, nincs second machine, nincs trükk — csak egy DGX Spark, egy NVFP4-es checkpoint, és egy production-relevant kérdés: futhatna-e a DocAI ezen a setup-on?
A számokat mind a saját Spark-omon mértem 2026. április 25-én, a Sehyo/Qwen3.5-122B-A10B-NVFP4 checkpointtal és a vLLM 0.19.2rc1.dev154+g1c2c1eb8b prebuilt wheel-jével eugr/spark-vllm-docker-ből.
A landscape gyorsan
Három élő NVFP4-kvantált 122B-A10B checkpoint van jelenleg:
- Sehyo/Qwen3.5-122B-A10B-NVFP4 — community-tested, vLLM
llm-compressor-ral kvantált, azextra_weights.safetensors-ban hozza az 5 GB BF16 MTP súlyokat. 81.5 GB. - txn545/Qwen3.5-122B-A10B-NVFP4 — NVIDIA Model Optimizer-rel kvantált, MTP súlyok NEM benne; kézi mergelés kell az eredeti 234 GB BF16-os modellből. 75.6 GB.
- RedHatAI/Qwen3.5-122B-A10B-NVFP4 — hivatalos NVIDIA verzió, llm-compressor +
save_mtp_tensors_to_checkpoint(). Hasonló méret.
A Sehyo-t választottam, két ok: az MTP súlyok már bent vannak (mentes egy órás extract-mergelési pénztől), és a community thread-ekben a legtöbb cross-validated mérés erre épül. A txn545 elméletileg picit jobb kvantálási minőséget adhat (NVIDIA hivatalos toolkit), de azt egy következő körre, amikor lesz magyar quality eval-harness-em — most a sebesség érdekes, és a sebességet az architektúra korlátozza, nem a kvantáló.
A build amit szerintem mindenkinek használnia kéne
A community fél éve evangelizálja az eugr/spark-vllm-docker-t, és ennek megvan az oka. A stock vLLM cu130-nightly image nem build-eli a CUTLASS NVFP4 MoE kerneleket SM121-re — a GB10 architektúrára nincs precompile-elt FP4 GEMM. Az eugr build pontosan ezt javítja: TORCH_CUDA_ARCH_LIST=12.1a, prebuilt FlashInfer és vLLM wheel-ek egy automated pipeline-ből, plus egy mods/ könyvtár modell-specifikus patch-ekkel.
Maga a build 2-3 perc, ha a base image (vllm/vllm-openai:cu130-nightly) már ott van a host-on. Source build-elés (40 perc FlashInfer + 20 perc vLLM) csak akkor kell, ha custom commit-ot vagy PR-t akarsz tesztelni.
git clone https://github.com/eugr/spark-vllm-docker.git
cd spark-vllm-docker
./build-and-copy.sh
Ennyi. Az image-et vllm-node néven menti.
A repo eddigi állapotában a recipes/qwen3.5-122b-fp8.yaml recipe-je cluster_only: true és tensor_parallel: 2 — vagyis a 122B FP8-at a maintainer két Spark-ra méretezte. A Sehyo NVFP4-es ~78 GB-ja viszont single Sparkon kényelmesen elfér, ezért a recipe-et figyelmen kívül hagytam, és a vllm-node image-et közvetlenül egy egyedi vllm serve paranccsal indítottam.
Egy meglepetés: FLASHINFER_CUTLASS SM121-en
Itt jött az első érdekesség. A community thread-ekben (kanthai/openclaw-spark, JungkwanBan/SPARK_Qwen3.5-122B-A10B-NVFP4) konzisztensen az áll, hogy a FlashInfer CUTLASS MoE FP4 backend SM121-en bukik, mert a cvt.e2m1x2 PTX instruction nincs támogatva a GB10-en. A megoldás: VLLM_USE_FLASHINFER_MOE_FP4=0, fall back native cutlass_moe_fp4 path-ra.
A vLLM 0.19.2 + a friss eugr build viszont más history-t mond. Az indítási logban:
INFO [nvfp4.py:283] Using 'FLASHINFER_CUTLASS' NvFp4 MoE backend out of potential backends:
['FLASHINFER_TRTLLM', 'FLASHINFER_CUTEDSL', 'FLASHINFER_CUTEDSL_BATCHED',
'FLASHINFER_CUTLASS', 'VLLM_CUTLASS', 'MARLIN', 'EMULATION'].
A vLLM autoselectelt FLASHINFER_CUTLASS-t, environment variable, kényszerítés, semmi.
A repo git log-ja mutatja az okot: d49fac1 Re-enable flashinfer_cutlass. Az eugr build mostanra olyan FlashInfer/CUTLASS verziót pull-ol, ami SM121-re már lefordul. A community lore tehát elavult, és érdemes nem szó szerint venni a régi forum thread-eket. Ami fél éve igaz volt, ma nem feltétlen.
Egy másik buktató: huggingface-cli deprecated
Apró, de nem-nyilvánvaló: a 2026 elején kiadott huggingface_hub 1.x megszüntette a huggingface-cli parancsot, helyébe hf lépett. A huggingface-cli download ... üres logot ad és kilép — az új CLI-t kell használni:
hf auth login # az xet rate limit miatt ez kötelező, public repokhoz is
hf download Sehyo/Qwen3.5-122B-A10B-NVFP4 \
--local-dir /opt/vllm/qwen35-122B/models/Qwen3.5-122B-A10B-NVFP4-Sehyo
Az xet backend (HF új CAS rendszere) anonim klienseket rate-limitel — 416 Range Not Satisfiable hibákat dobál public repokra is, ha nem vagy bejelentkezve. Egy gyors hf auth login token-nel megoldódik.
A 76 GB letöltése autentikálva ~15 perc volt egy gigabit kapcsolaton.
A cold start anatómiája
docker run -d --name vllm-122b-nvfp4 \
--runtime=nvidia --gpus all --privileged --network host --ipc=host \
-v /opt/vllm/qwen35-122B/models/Qwen3.5-122B-A10B-NVFP4-Sehyo:/models/qwen35-122b-nvfp4:ro \
-v ~/.cache/vllm:/root/.cache/vllm \
-v ~/.cache/flashinfer:/root/.cache/flashinfer \
-v ~/.triton:/root/.triton \
-e NCCL_IGNORE_CPU_AFFINITY=1 \
vllm-node \
vllm serve /models/qwen35-122b-nvfp4 \
--served-model-name qwen35-122b-nvfp4 \
--port 8000 --host 0.0.0.0 \
--max-model-len 131072 \
--max-num-seqs 4 \
--max-num-batched-tokens 8192 \
--gpu-memory-utilization 0.90 \
--kv-cache-dtype fp8 \
--enable-prefix-caching \
--trust-remote-code \
--enable-auto-tool-choice \
--tool-call-parser qwen3_coder \
--reasoning-parser qwen3 \
--speculative-config '{"method":"mtp","num_speculative_tokens":2}' \
--default-chat-template-kwargs '{"enable_thinking": false}'
A startup minden részletének időzítése:
| Phase | Idő (cold) | Idő (warm cache) | Megjegyzés |
|---|---|---|---|
| CUDA + tokenizer init | ~20s | ~20s | Konstans |
| Loading weights (76 GB) | 501s | 557s | Disk-bound, EXT4 |
| Drafter (MTP) loading | 73s | 84s | 5 GB BF16, ugyanonnan |
| torch.compile (backbone) | 36.5s | 10.1s | Cache hit jelentős |
| torch.compile (eagle_head) | 6.6s | 0.25s | Cache hit erős |
| FlashInfer autotune | ~10s | ~8s | Per-config tuning |
| CUDA graph capture | 12-17s | 11-15s | PIECEWISE mode |
| Total | ~12 perc | ~12 perc |
Két dolog érdekes itt.
Az első: a 76 GB-os weight loading 8 perc 21 másodperc — és ez nem javul cache-ből. A vLLM ezt explicitten meg is mondja az indító logban:
Filesystem type for checkpoints: EXT4. Checkpoint size: 75.89 GiB.
Available RAM: 41.40 GiB.
Auto-prefetch is disabled because the filesystem (EXT4) is not a recognized
network FS (NFS/Lustre) and the checkpoint size (75.89 GiB) exceeds 90% of
available RAM (41.40 GiB).
A 121 GiB unified memóriából csak 41 GiB jutott file cache-nek indításkor (a vLLM container, az egyéb processek, és a futáskor allokálódó struktúrák foglalják a többit). A 76 GB checkpoint nem fér el a 41 GB cache-be, így minden restartnál a teljes diszk-olvasást újra meg kell csinálni. NFS vagy Lustre fájlrendszeren a vLLM auto-prefetch tudna gyorsítani, EXT4-en nem.
A második: a torch.compile cache nagyot dob. A backbone modell compile-jánál 36.5s → 10.1s, a draft head-nél 6.6s → 0.25s. Ezeket mindenképp érdemes mounted volume-ban tartani (~/.cache/vllm-be), különben minden restart 40+ másodpercet pazarol.
Production szempontból a 12 perces startup nem rosszabb mint egy normál microservice deploy ablakja, de kell hozzá egy deploy stratégia: blue-green-szerű flow, ahol az új container felindul, smoke-tesztelődik, és csak utána kapcsolódik forgalomra.
Memory budget a 121 GiB unified pool-ban
Model weights (NVFP4): 76.02 GiB
KV cache (fp8, 128K, 4 seq): 30.33 GiB → 595,584 tokens
CUDA graph memory: 0.27 GiB
torch.compile / FlashInfer: ~5 GiB
Container + Python + scheduler: ~5 GiB
─────────────────────────────────────────
Total used: ~117 GiB
A gpu-memory-utilization 0.90 flagnél a vLLM 121.7 × 0.9 ≈ 110 GiB-ot foglal magának, és ebből kapja meg a 30 GiB KV cache pool-t. Ha 0.92-re emelnéd, +1 GiB KV-t kapnál, de OOM-kockázat van, mert a CUDA graph capture run-time-ban allokál.
A 595K token KV pool elég 4 párhuzamos 128K kontextusra is — 4 × 131072 = 524K, és a vLLM blokkos allokátora dinamikusan oszt el. A startup logban olvasható szám:
Maximum concurrency for 131,072 tokens per request: 12.89x
Ami azt mondja, hogy ha a kérések átlagosan 50%-os kontextus-kihasználtsággal mennek (ami real-world-ban realistic), akkor ~13 párhuzamos kérést bír. Worst case (mindenki maxon) ~4-5×.
Single-stream tok/s — 5 workload, 4 setup
Itt a fő összefoglaló a single-stream (concurrency=1) mérésekből. A benchmark scriptem 1 warmup + 3 measured run-t csinál minden workloadon, mediánt jelentek. MTP-2 mindenhol bekapcsolva, thinking off (--default-chat-template-kwargs '{"enable_thinking": false}'), temperature=0.
| Workload | 32K default | 32K tuned | 128K tuned | Description |
|---|---|---|---|---|
| Q&A | 24.7 | 25.2 | 25.6 | 20 token magyar prompt, 256 token output |
| Code | 30.1 | 29.7 | 30.1 | Python binary search request, 300 token |
| JSON-KIE | 31.0 | 30.7 | 30.9 | Magyar számla kinyerés JSON-ba |
| Magyar | 23.7 | 23.9 | 24.6 | 200 szavas magyar összefoglaló |
| Long-RAG-8K | 26.9 | 25.7 | 26.1 | 8K kontextus + kérdés, 256 token |
| Long-RAG-32K | n/a | n/a | 26.4 | 30K kontextus + kérdés, 256 token |
A három setup különbsége:
- 32K default:
--max-model-len 32768,--max-num-batched-tokens 4096, no prefix caching - 32K tuned:
--max-num-batched-tokens 8192,--enable-prefix-cachinghozzáadva - 128K tuned: ugyanaz,
--max-model-len 131072-re emelve
Két meglepő megfigyelés.
Az első: a 128K-s setup ugyanúgy gyors (sőt picit gyorsabb), mint a 32K-s, kis kontextusú kéréseken. Ezt nem vártam — a max_model_len növelése elméletileg több KV blokkot allokál és bonyolultabb scheduling-et okoz. A gyakorlatban ez nem érződik. Production ajánlás: --max-model-len 131072 egyszer, és ne fuss külön 32K-s instance-t. A unified memory budget is alig változik (30.33 GiB KV vs ~31 GiB volt 32K-n).
A második: a tuning szinte semmit nem ad single-stream-en. A --max-num-batched-tokens 4096 → 8192 változás ±1% tartományon belül mozog. A vLLM warning a default 4096-osnál azt mondta, hogy az MTP-vel suboptimal — ez koncurrent terhelésen lesz fontos, single-stream-en nem.
A --enable-prefix-caching viszont egy helyen ütött: a Long-RAG TTFT-jét drasztikusan csökkentette.
TTFT — ahol a prefix caching dolgozik
| Workload | 32K default TTFT | 32K tuned TTFT | 128K tuned TTFT |
|---|---|---|---|
| Q&A (~20 tok) | 0.27s | 0.27s | 0.27s |
| Code (~30 tok) | 0.28s | 0.28s | 0.28s |
| JSON-KIE (~200 tok) | 0.44s | 0.44s | 0.44s |
| Magyar (~30 tok) | 0.30s | 0.29s | 0.29s |
| Long-RAG-8K (~7500 tok) | 4.41s | 2.59s | 2.55s |
| Long-RAG-32K (~30K tok) | n/a | n/a | 3.87s (warm) / 18.11s (cold) |
A Long-RAG-8K-n a TTFT 4.41s → 2.59s (-41%) csak a --enable-prefix-caching flag-től. A benchmark script 4-szer küldi ugyanazt a hosszú prompt-ot egymás után, tehát a 2-3-4. run prefix cache hit, a TTFT egy része a fix prefix tokenizálását spórolja.
A Long-RAG-32K első cold run TTFT-je 18.11 másodperc, prefix cache hit-tel 3.87s — a vLLM majdnem teljes egészében cache-eli a 30K kontextus-prefix-et, és csak a néhány utolsó (nem-fix) tokent prefilleli újra. Ez egy 5×-ös gain ami real-world RAG-ban (ahol gyakran ugyanaz a system prompt + retrieved chunk-ok elejüek tartalmaznak fix elemeket) érdemi user perception javulást ad.
A vLLM a Mamba-cache + prefix-caching kombinációhoz ad egy figyelmeztetést:
Mamba cache mode is set to 'align' for Qwen3_5MoeForConditionalGeneration
... Its support for Mamba layers is experimental.
A Qwen3.5 hibrid GatedDeltaNet architektúrában a Mamba layer-ek prefix cache-elése kísérletes. A mérésekben nem láttam quality regressziót (a Long-RAG-8K outputjai értelmesek), de production-ben érdemes a chat_template_kwargs és a system prompt rögzített prefix-ét dokumentálni — mert ha az változik request-ről request-re, a prefix cache nem tud hit-elni.
MTP acceptance — workload-függő, és nagyon
Itt jön talán a legérdekesebb adat a cikkben. Az MTP acceptance rate (mennyi a draft tokenből fogadódik el) drámaian függ a workload típusától:
| Workload | MTP-2 acceptance (single-stream) |
|---|---|
| JSON-KIE | 100.00% (3/3 run azonos) |
| Code | 94-99% (run-by-run kicsi variance) |
| Long-RAG-32K | 74-81% |
| Long-RAG-8K | 71-78% |
| Q&A | 67-74% |
| Magyar | 63-67% |
A JSON-KIE 100%-os acceptance rate megdöbbentő. Egy 301 token output-ban minden speculatív tokent a draft eltalál. Magyarázat: a JSON struktúra annyira előrejelezhető (kapcsos zárójelek, ismétlődő kulcsnevek, vesszők, idézőjelek), hogy a kis MTP draft head triviálisan kitalálja a következő tokeneket. A modell tényleg csak a mező-értékeknél „gondolkodik” — a struktúrát végigfutja.
A natural language workloadok (Magyar, Q&A) ~63-70%-on mozognak, ami a community báziseknek megfelelő szám.
Production következmény: a DocAI-ban a strukturált output use case-ekre (számla KIE, proposal canvas JSON, company lookup eredmény) az MTP gyakorlatilag dupla decode tok/s-t ad. A natural language chat agent-en csak ~1.4×-es gain.
A 100% acceptance ihlet tovább: érdemes lenne num_speculative_tokens=3-mal próbálkozni. Ha a draft 2 tokent triviálisan eltalál, valószínűleg 3-at is 80%+ pontossággal — és 80% × 3 token = 2.4 elfogadott token per step több mint a jelenlegi 100% × 2 token. Ez egy következő körre marad.
Concurrent stress — ahol a Spark megmutatja magát
Eddig single-stream számokat néztünk, ami egy felhasználós scenario. Production-ben ritkán ez van — több párhuzamos kérés érkezik, és az aggregate throughput (nem a per-request) az ami számít.
Egy benchmark_concurrent.py scriptet írtam, ami N szállas worker pool-lal hív API-t megadott időtartamban, mix-elt workload típusokkal. Három mix profile-t teszteltem:
uniform_short: 4 párhuzamos szál, mind rövid prompt (Q&A + Code + JSON + Magyar round-robin), 90 másodpercmixed_typical: 4 párhuzamos szál, 3 rövid + 1 Long-RAG-8K (a „DocAI realistic mix”), 90 másodperclong_only_128k: 4 vagy 2 párhuzamos szál, mindegyik ~108K token kontextus, 90/180 másodperc — a stress test
A számok:
| Mix | Concurrency | Duration | Reqs done | Aggregate tok/s | MTP accept |
|---|---|---|---|---|---|
| uniform_short | 4 | 90s | 20 | 63.86 | 76.13% |
| mixed_typical | 4 | 90s | 20 | 57.65 | 73.89% |
| long_only_128k | 4 | 90s | 8 | 14.65 | 75.89% |
| long_only_128k | 2 | 180s | 6 | 6.54 | 75.84% |
Az uniform_short aggregate 63.86 tok/s — 2.1× a single-stream JSON-KIE-csúcs (30.9 tok/s). Pontosan ezt vártam egy MoE modelltől: 4 párhuzamos request különböző expertekt aktivál, így a 273 GB/s memory bandwidth jobban kihasználódik (csak ~10B aktív paraméter olvasódik be tokenenként, és a 4 request különböző subset-et használ).
A mixed_typical 57.65 tok/s — kicsit alacsonyabb, mert a Long-RAG-8K a 4 szál egyikét fogja prefill alatt. A többi 3 szál még eközben generál, ezért az aggregate még mindig magas.
A long_only_128k adat azonban a sztori fő tanulsága:
A Spark fal: 4× 100K-s párhuzamosan kéne — sajnos nem
Az első mérés 4 szálas, 90 másodperc — 0 request fejeződött be. Ránézve a vLLM logba: prompt overflow. A workload script make_long_rag_messages(115000) becslése 4 char/token volt, magyar szöveggel az tényleges tokenizáció ~1.14× annyi → 130817 input + 256 output = 131073, 1 token overflow a 131072 limiten. A vLLM mindegyik kérést 400 Bad Request-tel utasította vissza, és a script errors: 0 mezője hibásan jelentett (a lehetőség azonnal kapott választ, nem az explicit timeout volt a probléma).
A target tokent 95000-re csökkentve (~108K tényleges magyar token), a tényleges állapot megmutatkozott:
c=2, 180 másodperc:
- 6 request fejeződött be 182.3 másodperc alatt → kb. 60s/request átlag
- TTFT p50: 20 másodperc (két párhuzamos prefill chunked módon)
- TTFT p95: 112 másodperc (worst-case egy késő érkezőre)
- Decode p50: 20.6 tok/s per request (közel single-stream szint)
- Aggregate: 6.54 tok/s
c=4, 90 másodperc:
- 8 request fejeződött be 106.2 másodperc alatt → ~52s/request
- TTFT p50: 20.66s, p95: 40.33s
- Decode p50: 6.2 tok/s per request
- Aggregate: 14.65 tok/s
A c=4 vs c=2 aggregate-ben 2.2× — vagyis több párhuzamosság kicsit jobb a teljes throughputra, de a per-request decode tok/s 20.6-ról 6.2-re zuhan (3.3×-os esés). Egy egyedi user szempontból ez katasztrofális: a 6.2 tok/s azt jelenti, 1 token / 160ms — ahol egy 200 szavas magyar válasz (~250 token) wall-clock-ban ~40 másodperc, plus a 20s prefill, plus a queue-be várás.
A Spark nem alkalmas több felhasználós, kontextus-nehéz interaktív loadra ezzel a 122B-NVFP4 modellel. Mire való:
- Single-user interaktív DocAI chat rövid promptokkal (24-31 tok/s, 0.3-0.5s TTFT) ✅
- DocAI batch KIE strukturált JSON output (31 tok/s, 100% MTP acceptance) ✅
- Single RAG query akár 30K kontextusig (3.87s warm TTFT) ✅
- Multi-user chat rövid promptokkal (4 user, ~16 tok/s/user, jó UX) ✅
- Multi-user RAG középhosszú kontextussal (~57 tok/s aggregate) ⚠️ degraded UX
- Multi-user dokumentum-elemzés 100K+ kontextussal ❌ nem alkalmas
A 6-os pontot második Sparkkal lehetne enyhíteni (TP=2 cluster, ~70 tok/s aggregate a community szerint), vagy egy NVFP4 backend bekapcsolásával (Albond v2 hybrid INT4+FP8 + INT8 LM head ~51 tok/s single-stream a community szerint, de quality regresszió kockázat).
A számok mögött: mit is mértünk valójában
Egy zárszó arról, hogy a fenti táblázatok mit jelentenek és mit nem. A benchmark egy fix prompt-ot és fix max_tokens-t használ, és a script ugyanazt a 4-5-6 promptot futtatja. Ez a setup kifejezetten kedvez a prefix caching-nek — a Long-RAG-8K-n a 2.59s TTFT a 4-szer ugyanazon prompt-tal mért érték. Egy real-world DocAI use case-ben, ahol minden RAG retrieval más chunkokat hoz, a TTFT inkább a cold first run-hoz lesz közelebb (4.4-18 másodperc).
A decode tok/s ezzel szemben nagyrészt prompt-független (a memory bandwidth-bound throughput nem nagyon függ attól, mit generálsz, csak hogy mennyit). A ~25-31 tok/s single-stream tartomány valós DocAI prod terhelésen is hasonló lesz.
Egy másik kaveat: a enable_thinking: false flag-gel mértünk. Ezt KIE-feladatokra hivatalosan ajánlják (a Qwen3.5-ös research card és a community thread-ek konzisztensen). Egy „thinking on” mérés más sztorit mondana — egy egyszerű Q&A 1500+ tokenre nőne (a model magában gondolkodik), és a real wall-time arányosan többszörös lenne. Erre a DocAI-nak nincs szüksége.
Konklúzió: érdemes-e DocAI-be tenni?
Még nem. Két tényező hiányzik a végleges ítélethez.
Az első: quality benchmark. A jelenlegi prod modell a Qwen3.6-35B-A3B-FP8. A 122B-NVFP4 elméletileg több paraméterrel okosabb, de az NVFP4 quantization ront valamennyit. Hány százalékot pontosabb a magyar számla KIE-én? Mennyivel jobb a magyar legal Q&A? Ezt a mérést egy következő körben fogom csinálni, a memóriámban már szereplő „DocAI magyar eval harness” részeként. A throughput szempontjából:
| Modell | Single-stream JSON-KIE tok/s | Aggregate (4 user) |
|---|---|---|
| Qwen3.6-35B-A3B-FP8 (jelenlegi prod) | ~50-60 | ~80-100 |
| Qwen3.5-122B-A10B-NVFP4 (mért) | 30.9 | 63.86 |
A 122B lassabb mint a 35B-ABF8 ezen a workload-on. Nyilvánvalóan: kétszer annyi memóriát kell végigolvasni tokenenként. Az MTP behozza ezt 2.1×-szel, plus a 100% acceptance JSON-on, de még akkor is alulmarad.
A második: a valódi production usage pattern. A jelenlegi DocAI single-tenant — egy magyar SME ügyfél, max 3-5 user párhuzamosan, többségében rövid chat + KIE batch + alkalmi RAG. Erre a 122B-NVFP4 vagy a 35B-FP8 mindketten elégségesek. Ha a quality előny érzékelhető — pl. a magyar legal Q&A markánsan jobb a 122B-n —, akkor a sebesség-veszteség elfogadható ár, mert a user latency még akceptábilis (32K kontextusú JSON-KIE 10s-on belül megvan). Ha a quality előny nem érzékelhető, maradunk a 35B-FP8-on, mert single-stream gyorsabb és kevesebb memory pressure.
A Spark hardware oldalt a mérések megerősítik: single-stream 122B-NVFP4 production ready single Sparkon, multi-stream középhosszú kontextusra is megfelelő, multi-stream 100K+ kontextusra nem skálázódik.
Mit lehet még csinálni
Pár kísérlet ami a következő körre marad:
num_speculative_tokens=3— a JSON-KIE 100% acceptance arra utal, hogy a 2-es draft trivialísan eltalálódik, érdemes próbálkozni 3-mal. Becsült gain: +20-30% strukturált workloadon.- txn545/Qwen3.5-122B-A10B-NVFP4 kontroll-mérés — picit más kvantáló (NVIDIA Model Optimizer), kérdés hogy a magyar quality változik-e.
- Albond v2 hybrid INT4+FP8 — community report szerint single Sparkon 51 tok/s, de „Qwen3.5-35B Native FP8 + MTP is much better than Qwen3.5-122B int4-AutoRound” — quality regresszió kockázat.
- Második Spark cluster (TP=2) — a 397B-MoE-hez amúgy is kell, és a 122B-n a community 70 tok/s körüli aggregate-et lát. Ha a multi-user pattern elindul, ez lehet a megoldás. Pénzkérdés.
- SGLang — a
txn545checkpoint tartalmazza az SGLang-támogatást is. Egyező hardware-en nem várható radikális gain (memory bandwidth bound), de a strukturált output (constrained JSON) gyorsabb lehet. Build-elési költség nem kicsi, ezért csak ha a JSON-KIE sebesség kifejezett bottleneck.
Pár utolsó adat a teljességhez
A 14 perces hidegindítás után a Spark stabil futott 90+ percen át a benchmark sorozat alatt, OOM nélkül, restart nélkül. A nvidia-smi 11 GB GPU memory használatot mutatott (a többi ~76 GB CPU oldalán van a unified memóriában). A container 3.22% CPU-t használt idle-en, és a vLLM internal scheduler-loop kb. 10-20% CPU-t használt active inference alatt.
Egy single Spark áram-felvétele a benchmark alatt mért módon: 3-10W idle, ~150-180W full inference. A LPDDR5x memory az ami fűt, nem a GPU compute (273 GB/s sustained random access ezen a chip-méret alatt komoly igény).
A teljes setup (build, modell letöltés, 4 mérési kör, 3 restart) ~3 óra volt egy-egy döntés között a felhasználói részemen, ami azt mondja, hogy 24 órán belül egy tetszőleges DGX Spark tulajdonosnak végrehajthatóak ezek a mérések. A eugr/spark-vllm-docker repo, a Sehyo checkpoint, és a fenti 8 vLLM flag — ennyi.
A számok alapján a 122B-NVFP4 egy single Sparkon technikailag megy, és bizonyos use case-ekre alkalmas. A produktív döntés — DocAI-ben jó-e — egy quality eval-tól függ, és arra még nincsenek számaim. De a sebességet most mérjük, és tudunk mire mondani igent.
Rendszer: NVIDIA DGX Spark, GB10 (SM 12.1), 128 GB LPDDR5x unified memory
Modell: Sehyo/Qwen3.5-122B-A10B-NVFP4 (76 GB checkpoint, MTP súlyokkal együtt)
vLLM: 0.19.2rc1.dev154+g1c2c1eb8b (eugr/spark-vllm-docker prebuilt wheel, cu130-nightly base, 2026-04-25)
MoE backend: FLASHINFER_CUTLASS (autoselected SM121-en)
Benchmark eszköz: saját benchmark_concurrent.py + vllm bench serve
A teljes JSON eredmény-szett, a docker run paraméterek és a concurrent benchmark script elérhető — ha érdekel a reprodukció vagy a részletes percentile-eloszlások, írj.