~/blog/dgx-spark-zimage-turbo-nvfp4-bench

Z-Image Turbo · part 1

[實戰] Z-Image Turbo 教戰守則:6 種配置怎麼選,1.37× 加速 + 44% 省 RAM

2026-05-048 分鐘閱讀#z-image#comfyui#nvfp4#fp8English
cat --toc

TL;DR

DGX Spark GB10 跑 Z-Image Turbo,N=10 隔離 GPU 實測 6 種量化組合。NVFP4 transformer 5.50s warm(比 BF16 7.55s 快 1.37×),三條 FP8 path 全比 BF16 慢(8.19-8.45s)。推薦:NVFP4 + qwen_3_4b FP8 mixed encoder,disk 10.4 GB(省 ~49%),工作集 11.5 GB(BF16 是 20.6 GB,省 44%),warm 速度跟 NVFP4+BF16 encoder 同 tier。⚠️ weight_dtype=fp8_e4m3fn cast 路徑記憶體不會變小,要省 RAM 必須用 native 量化檔。為什麼 FP8 慢留給下一篇。

白話版:Z-Image Turbo 是什麼,為何要做這份 bench

Z-Image Turbo 是 Alibaba 通義 Tongyi-MAI 在 2025 年 11 月底發布的開源 image gen 模型(Apache 2.0、商用 OK,以官方 repo 的 LICENSE 為準)。distilled 版只要 8 step 就能生圖。本文用的是 Comfy-Org repack — 把官方權重切成 ComfyUI 直接吃的 split_files/ 結構,額外打包了 NVFP4 / FP8 mixed encoder 量化版。

如果你不熟「量化」(quantization)— FP8 / NVFP4 / BF16 這幾個數值格式分別是什麼、為什麼壓位元能省 memory、為什麼有時候反而會慢 — 先看入門:

簡而言之:image gen 用的是跟 LLM 同一套 FP8 / NVFP4 / BF16 量化格式,model file 也是 .safetensors 同格式,只差 inference 的 backend(LLM 走 vLLM / SGLang,image gen 走 ComfyUI + comfy_kitchen)

DGX Spark 是 NVIDIA 桌上型 AI 工作站(售價約 3,000 美元),用 GB10 GPU + 128 GB unified memory + 273 GB/s 記憶體頻寬。我在這台上跑 6 種 Z-Image Turbo 量化組合,測速度跟資源,給你一張可以照抄的最佳組合表。


為何要做這篇

社群討論 NVFP4 vs FP8 哪個比較好的時候,大多假設「位元越少越快」。但這假設在 GB10 上不成立 — 過去在 LLM 端(Part 19:NVFP4 在 GB10 是陷阱)已經給出反例,FP8 比 NVFP4 快 32%。

那 image gen 端呢?DiT(Diffusion Transformer)forward pass 跟 LLM autoregressive decode 訪問模式完全不同,結論不能直接套。得自己量


測試 stack

環境

  • 硬體: DGX Spark (GB10 / SM12.1,128 GB unified,273 GB/s LPDDR5x)
  • OS: Ubuntu,nvidia driver 580,CUDA 13.0
  • ComfyUI: 0.20.1,PyTorch 2.10.0+cu130,comfy_kitchen 0.2.8
  • 隔離 GPU:測試前 docker stop qwen-abliterated(關掉 vllm-gx10 LLM 釋出 70 GB)
  • idle VRAM:41 GB(系統 + ComfyUI + buffer cache)

6 個 config

labeltransformer 檔weight_dtypeencoder 檔
BF16+BF16(baseline)z_image_turbo_bf16.safetensors(12.3 GB)defaultqwen_3_4b.safetensors(8.0 GB)
FP8cast e4m3fn同上(BF16 source)fp8_e4m3fn同 BF16
FP8cast FAST同上fp8_e4m3fn_fast同 BF16
FP8scaled Kijaiz-image-turbo_fp8_scaled_e4m3fn_KJ.safetensors(5.7 GB)default同 BF16
NVFP4+BF16z_image_turbo_nvfp4.safetensors(4.5 GB)default同 BF16
NVFP4+FP8e(推薦)同 NVFP4defaultqwen_3_4b_fp8_mixed.safetensors(5.6 GB)

NVFP4 transformer 跟 FP8 mixed encoder 從 Comfy-Org/z_image_turbo 官方 repo 抓。FP8 scaled 版本是 Kijai/Z-Image_comfy_fp8_scaled 社群預量化版,帶 weight_scale tensor,跟 cast 路徑用不同 ComfyUI pipeline。

推理參數(全 config 固定)

KSampler: steps=8, cfg=1.0, sampler=res_multistep, scheduler=simple
ModelSamplingAuraFlow: shift=3
Latent: EmptySD3LatentImage 1024×1024
Negative: ConditioningZeroOut(FLUX 系慣例,空字串 CLIPTextEncode 不對)
CLIPLoader: type=lumina2(Z-Image 借 Lumina2 pipeline)

測什麼

  • Warm latency:同 prompt + 同 seed,先 1 個 cold 把 model 載進 VRAM,然後連跑 N=10 個 warm,記每次 wall-clock
  • Peak VRAM:背景 thread 200ms 取樣 ComfyUI /system_stats 的 vram_used,取整段 max
  • Cold latency:第一次載 model 進 VRAM 的時間(disk → RAM + JIT compile)

結果

Warm latency(N=10 mean ± std)

configwarm mean ± stdminmaxvs BF16
BF16+BF167.55 ± 0.01s7.54s7.57s1.0× baseline
FP8cast e4m3fn8.27 ± 0.10s8.15s8.46s0.91× ❌ 慢 0.72s
FP8cast FAST8.45 ± 0.01s8.45s8.47s0.89× ❌ 最慢
FP8scaled Kijai8.19 ± 0.04s8.14s8.24s0.92× ❌ 慢 0.64s
NVFP4+BF165.50 ± 0.07s5.44s5.58s1.37×
NVFP4+FP8e(推薦)5.52 ± 0.10s5.43s5.74s1.37×

兩個重點:

  1. NVFP4 transformer 是真贏家 — warm 5.50s,std 0.07s,跟 BF16 7.55s 的差距(2.05s)遠大於 noise(每邊 std 0.07s,離得最近 max-min 也差 1.86s)。1.37× 加速是穩的。

  2. 三條 FP8 path 全比 BF16 慢 — 最意外。fp8_e4m3fn_fast 還比 standard 多慢 0.18s,本來預期 fast 會走真 FP8 matmul kernel(torch._scaled_mm),結果反而 overhead 最大。Kijai 預量化版本(帶 weight_scale)略快於 cast 版,但仍輸 BF16 0.64s。

  3. encoder 量化對 warm 速度幾乎無影響 — NVFP4+BF16 encoder vs NVFP4+FP8 mixed encoder,5.50 vs 5.52s,std 範圍內。Z-Image 一張圖只 encode 一次 prompt,encoder 大小對 inference time 不影響。

Cold latency

configcold(s)
BF16+BF1660.9
FP8cast e4m3fn47.2
FP8cast FAST24.6
FP8scaled Kijai21.4
NVFP4+BF1612.5
NVFP4+FP8e16.3

主要由 model 大小決定(BF16 12.3 GB > FP8 5.7 GB > NVFP4 4.5 GB)。NVFP4 cold 12.5s 比 BF16 60.9s 快 5×,冷啟動省下大量等待時間

模型工作集(ComfyUI process RSS peak,扣掉 idle baseline)

configRSS peak工作集(扣 idle ComfyUI 0.98 GB)vs BF16
BF16+BF1621.62 GB20.64 GB0(baseline)
FP8cast e4m3fn21.62 GB20.63 GB±0(沒省!)
FP8cast FAST21.68 GB20.69 GB±0(沒省!)
FP8scaled Kijai15.95 GB14.97 GB-5.67 GB
NVFP4 + BF1614.75 GB13.76 GB-6.88 GB
NVFP4 + FP8 ⭐(推薦)12.50 GB11.52 GB-9.12 GB(省 44%)

意外的發現:

  • FP8 cast(weight_dtype=fp8_e4m3fn)記憶體沒省 — 它先載入 BF16 完整檔(12.3 GB)後 in-memory cast 成 FP8,實際 process RSS 跟 BF16 一樣。所以 weight_dtype flag 只改變 forward 計算路徑,不影響 model 在記憶體裡的實際大小
  • 真省記憶體的只有 native quantized 檔(NVFP4 transformer / FP8scaled Kijai / FP8 mixed encoder)— 這些檔在 disk 上就已經是壓縮格式,載進記憶體也是壓縮格式
  • NVFP4 + FP8 mixed encoder 工作集 11.52 GB,比 BF16 baseline 20.64 GB 省 44%

(早期版本本篇貼過「70 GB peak VRAM」這種大數字 — 那是 ComfyUI /system_stats 的 system-wide vram_used,含 OS + Linux page cache + 其他 process,不是純 ComfyUI process 的 model 工作集。Process RSS peak 才是真實 model footprint,本表已換成正確 metric。)


6 張 warm sample(同 prompt + 同 seed=42)

Prompt:a photorealistic portrait of a young woman with long flowing black hair, soft natural lighting, gentle smile, sitting in a coffee shop, depth of field, highly detailed eyes

BF16 + BF16(7.55s baseline)
BF16 + BF16
FP8cast + BF16(8.27s)
FP8cast + BF16
FP8cast FAST + BF16(8.45s)
FP8cast FAST + BF16
FP8scaled + BF16(8.19s)
FP8scaled + BF16
NVFP4 + BF16(5.50s)
NVFP4 + BF16
NVFP4 + FP8 ⭐(5.52s,推薦)
NVFP4 + FP8

肉眼看 6 張人像沒明顯崩壞 — 髮絲、眼神、咖啡背景都站得住。但寫實人像對 FP4 來說是相對溫和的 prompt,複雜中文 / 文字 / 細節密 / anime 風的 prompt 是不是也站得住,Part 2 用 LPIPS + CLIPScore 雙軸量化測試會給答案


推薦組合

NVFP4 transformer + qwen_3_4b FP8 mixed encoder + ae VAE

數值
Warm 速度5.52s / 1024×1024 圖
比 BF16 加速1.37×
Cold 啟動16.3s
模型工作集 RSS11.52 GB(BF16 baseline 20.64 GB,省 44%)
Disk 占用4.5 + 5.6 + 0.34 = 10.44 GB
比 BF16 disk 省~49%(BF16 整套 20.64 GB)

下載清單:

HF_REPO=https://huggingface.co/Comfy-Org/z_image_turbo/resolve/main

# transformer
curl -L -o models/diffusion_models/z_image_turbo_nvfp4.safetensors \
  $HF_REPO/split_files/diffusion_models/z_image_turbo_nvfp4.safetensors

# text encoder (FP8 mixed)
curl -L -o models/text_encoders/qwen_3_4b_fp8_mixed.safetensors \
  $HF_REPO/split_files/text_encoders/qwen_3_4b_fp8_mixed.safetensors

# vae
curl -L -o models/vae/ae.safetensors \
  $HF_REPO/split_files/vae/ae.safetensors

ComfyUI workflow JSON 範本(API 直接 POST 到 /prompt):

{
  "1": {"class_type": "UNETLoader", "inputs": {
    "unet_name": "z_image_turbo_nvfp4.safetensors",
    "weight_dtype": "default"}},
  "2": {"class_type": "CLIPLoader", "inputs": {
    "clip_name": "qwen_3_4b_fp8_mixed.safetensors",
    "type": "lumina2", "device": "default"}},
  "3": {"class_type": "VAELoader", "inputs": {"vae_name": "ae.safetensors"}},
  "11": {"class_type": "ModelSamplingAuraFlow", "inputs": {"model": ["1", 0], "shift": 3.0}},
  "4": {"class_type": "CLIPTextEncode", "inputs": {"text": "<your prompt>", "clip": ["2", 0]}},
  "5": {"class_type": "ConditioningZeroOut", "inputs": {"conditioning": ["4", 0]}},
  "6": {"class_type": "EmptySD3LatentImage", "inputs": {"width": 1024, "height": 1024, "batch_size": 1}},
  "7": {"class_type": "KSampler", "inputs": {
    "model": ["11", 0], "seed": 42, "steps": 8, "cfg": 1.0,
    "sampler_name": "res_multistep", "scheduler": "simple",
    "positive": ["4", 0], "negative": ["5", 0],
    "latent_image": ["6", 0], "denoise": 1.0}},
  "8": {"class_type": "VAEDecode", "inputs": {"samples": ["7", 0], "vae": ["3", 0]}},
  "9": {"class_type": "SaveImage", "inputs": {"images": ["8", 0], "filename_prefix": "zimage"}}
}

幾個容易踩的雷:

  • CLIPLoader.type 必須設 lumina2(Z-Image 借 Lumina2 pipeline,沒有獨立 z_image type)
  • 必走 ModelSamplingAuraFlow shift=3 patch(少這個 sampling 不收斂)
  • Latent 用 EmptySD3LatentImage 不是 EmptyFlux2LatentImage
  • 上面下載命令把檔直接放在 models/{diffusion_models,text_encoders,vae}/ 下,workflow 裡 unet_name/clip_name/vae_name 就是純檔名(不帶子目錄)。如果你保留 HF 原 split_files/... 子結構下載,workflow 路徑也要帶 split_files/diffusion_models/... 前綴對應

方法學注意

這份 N=10 資料是 publication-grade,但有限制:

  1. 單 prompt 單 seed 測 latency — 不同 prompt 訪問模式不同,但量化路徑差異主要在 transformer / encoder kernel,跟 prompt 內容無關,所以單 prompt 結果應該可外推
  2. 品質沒測 — Part 2 用 LPIPS + CLIPScore 雙軸跑 6 prompt × 多 seed
  3. mechanism 沒解 — 為什麼 FP8 比 BF16 慢、為什麼 NVFP4 比兩者都快?Part 3 深挖
  4. GB10 uniquevram_used 是 unified memory,跟 dGPU 上的 dedicated VRAM 計法不同。RTX 5090 / B200 上結果可能完全不同

跟 Part 19 LLM NVFP4 結論的對比

Part 19 結論:LLM 端(vLLM 跑 Qwen 3.6 35B)NVFP4 比 FP8 慢 32%,FP8 永遠贏。

本篇結論:Image gen 端(ComfyUI 跑 Z-Image Turbo)NVFP4 比 FP8 快 33%,而且 FP8 比 BF16 還慢。

完全相反。但這不是「同硬體上 NVFP4 vs FP8 的對立 evidence」 — LLM trap 是 vLLM Marlin kernel 在 SM12.1 上的特定品質問題,Image gen 走 PyTorch + comfy_kitchen 不同 backend。結論依 stack/workload 而異,不是 GB10 universal truth

為什麼這兩條 path 上量化會走不同路徑、得到相反速度結論?Part 3 深挖 ComfyUI ops.py + comfy_kitchen 的 kernel dispatch 邏輯。


相關閱讀

常見問題

Z-Image Turbo 在 DGX Spark GB10 上跑多快?
1024×1024 8 step 跑 N=10 隔離 GPU 實測:BF16 baseline 7.55s warm,NVFP4 transformer 5.50s warm(1.37× 加速),三種 FP8 transformer(cast 標準 / cast fast / Kijai 預量化版)全部都比 BF16 慢 0.6-0.9s。
DGX Spark 跑 Z-Image Turbo 推薦哪個量化組合?
**NVFP4 transformer + qwen_3_4b_fp8_mixed encoder**。warm 5.52s(跟 NVFP4+BF16 encoder 同 tier 但 disk 省 2.4 GB),模型工作集 RSS 11.5 GB(BF16 是 20.6 GB,省 44%),整套 disk 10.4 GB(BF16 整套 20.6 GB 的一半,省 ~49%)。
FP8 transformer 為何反而比 BF16 慢?
三種 FP8 path 都比 BF16 慢:weight_dtype=fp8_e4m3fn 慢 0.72s、fp8_e4m3fn_fast 慢 0.90s、Kijai 預量化 scaled 版 慢 0.64s。為什麼留給 Part 3 深挖,本篇只報實測結果。
Z-Image Turbo 量化版品質會崩嗎?
本篇只看速度+資源,品質測試留給 Part 2 用 LPIPS + CLIPScore 雙軸跑 6 prompt × 4 config × 3 seed 量化。眼睛看 6 張 sample warm 圖人像沒明顯崩壞,但這是寫實 prompt 對 FP4 是最弱 stress test,不能外推。