前シリーズの続編です。1台の DGX Spark(GB10, 128GB)で、
現行 TensorFold(Qwen3.8-27B MLX-4bit + DFlash2) と
SGLang(Qwen3.8-27B NVFP4 + DFlash2) を同一スクリプトで比較しました。
IP・ホスト名はプレースホルダに置き換えています。
TL;DR
-
単流decode: TensorFold が 約1.55×速い(149–150 vs 96 tok/s)。
-
エージェント型(think): TensorFold が 約3×速い(12.9s vs 40.2s)。
-
prefill: ほぼ同等(両者 ~2,100 tok/s)。
-
並行時の劣化: どちらも本質は同じ(長文脈はレイテンシ ≒ N倍)。SGLangはprefillが~1.35×速く公平配分(最悪待ちが小さい)が、decodeは遅い。
- 結論: 速度目的でのSGLang移行は不要。SGLangの価値は速度ではなく機能(penaltyでnon-thinkingが動く等)。
1. 検証設計
-
1GPU・1モデル同時のみ → A/Bは逐次(TensorFold測定→停止→SGLang起動→測定→復帰)。
- 同一スクリプト(
bench4.py: prefill 30k cold×2 + decode 600トークン×2、benchB.py: tool多ターン)。
- 注意: 測定中はユーザの opencode が同時アクセスすることがあり、ノイズ源。両者クリーン値で比較。
2. SGLang セットアップ
- イメージ:
lmsysorg/sglang:dev-cu13
- モデル:
nvidia/Qwen3.8-27B-NVFP4 + z-lab/Qwen3.8-27B-DFlash2(DFlash2)
- 主要フラグ(DGX Sparkのコミュニティレシピ準拠 = SGLang公式cookbook相当):
--speculative-algorithm DFLASH --speculative-num-draft-tokens 16 --mem-fraction-static 0.50 --attention-backend flashinfer --mamba-radix-cache-strategy extra_buffer ...
注意: HF_HUB_OFFLINE 未指定だと起動ハングすることがあり、指定で解消しました。
3. 速度(同一ベンチ)
| 指標 |
TensorFold (MLX-4bit+DFlash2) |
SGLang (NVFP4+DFlash2) |
| prefill 30k cold |
~2,080–2,100 tok/s |
~2,065–2,157 tok/s |
| decode 600 |
149–150 tok/s |
96 tok/s(draft16) |
SGLang ドラフト深さスイープ(--speculative-num-draft-tokens)
| draft |
decode 600 |
| 8(incoai公式値) |
72 tok/s |
| 16(コミュニティレシピ) |
96 tok/s(最良) |
| 32 |
30kプロンプトで 400 Bad Request(深すぎ) |
→ prefillは同等、decodeはTensorFoldが約1.55×速い。ドラフトは16が最良。
4. エージェント型(tool多ターン)
| 構成 |
TensorFold |
SGLang |
| fast |
4.2s |
6.5s |
| think |
12.9s |
40.2s |
| think_budget256 |
12.6s |
35.1s |
| think_budget512 |
12.5s |
24.8s |
- 1トークンあたりでも TensorFold ~55 vs SGLang ~33 tok/s。
- SGLangは生成トークン数も多い(think合計 1348 vs 711、テンプレ/effort差)。
- → エージェント用途では TensorFold が約3×速い。
5. 並行時の劣化率(ここが実運用で効く)
5.1 短い文脈のdecode(per-stream, 基準N=1)
| N |
TensorFold |
劣化率 |
SGLang |
劣化率 |
| 1 |
147.6 tok/s |
0% |
97.2 |
0% |
| 2 |
130.4 |
−11.7% |
87.7 |
−9.8% |
| 4 |
108.2 |
−26.7% |
74.0 |
−23.9% |
集約スループットのスケール効率(理想=N×): TensorFold 1.77×/2.93×、SGLang 1.80×/3.02×。
5.2 長い文脈のprefill(レイテンシ膨張, 基準=単発)
| N |
TensorFold |
膨張 |
SGLang |
膨張 |
| 1 |
12.4s |
1.00× |
9.2s |
1.00× |
| 2 |
13.4 / 27.6s |
1.08× / 2.23×
|
18.3 / 18.3s |
1.99× / 1.99× |
| 4 |
13.6/25.4/37.2/48.4s |
…/ 3.90×
|
36.1s ×4 |
3.92× ×4 |
-
最悪待ちは両者ほぼ同じ(≒N×)。差は配分方針のみ:
- TensorFold = 逐次(先着は速い、最後がN×)
- SGLang = 公平(全員がN×)
- SGLangはprefillが~1.35×速いので総時間は少し短い。
5.3 混在(長prefill + 短decode)
| エンジン |
短decode 単発 |
混在 |
劣化 |
| TensorFold |
4.0s |
13.0s |
3.25× |
| SGLang |
6.2s |
14.8s |
2.39× |
6. 結論
-
「SGLangでTensorFoldと同等以上」は実測では達成できなかった。むしろ TensorFold が速い(decode ~1.55×、agentic ~3×)。
- 推定理由:
- TensorFoldは15ノードの木で投機(SGLangは線形チェーン)→ 1ステップの受入が多い。
- SGLangのNVFP4(~16GB)はMLX-4bit(~14GB)より重い → AR帯域で不利。
- ただし SGLangの価値は速度以外:
-
penalty対応 → non-thinkingが動く(前回のループ問題の解決)
- prefillが速く、並行配分が公平
- 1Mコンテキスト、NVFP4品質、MTP選択肢
-
並行の劣化はエンジン非依存(支配要因は「プロンプト長 × 同時数」)。長文脈を同時に走らせない/文脈圧縮が最も効く。
まとめ
- 速度だけを見るなら TensorFold 継続が最良。
-
non-thinking を安定して使いたいなら SGLang に価値がある(→ ③移行編)。
- 並行性能はエンジンで解決しない。文脈長のマネジメントが本質。
数値は筆者環境での実測です。負荷・チェックポイント・設定で変動します。