返回文章列表
2026年8月13日 14 分鐘閱讀

h3.c 跑 MiniMax H3 實測:M5 Pro 64GB 記憶體與 VAE 接縫修正

在 M5 Pro 64GB 上用 h3.c 跑 MiniMax H3,整理 134 GiB 權重下載、Metal 建置、效能與尺寸限制,以及 Video VAE 接縫修正。

h3.c 在 M5 Pro 上加速 MiniMax H3 推理的極簡實物攝影封面

用 ComfyUI 跑通 MiniMax H3 之後,我又在同一台 64GB M5 Pro 上測了 h3.c。它用 C 與 Metal 實作 MiniMax H3 推理,不依賴 PyTorch;代價是要下載約 134GiB 的 BF16 權重。

h3.c 最明顯的優勢是記憶體行為較容易預測。在 512×512、22 幀、20 步的測試中,峰值為 18.88 GiB,沒有觀察到新的 swap。相較之下,我的 ComfyUI 測試在較大的工作量下會面臨明顯的記憶體壓力。

小問題:在 576×1024、124 幀的直式影片上,video VAE 使用 320px tile 時會留下棋盤格狀接縫;改回官方 256px 後已有明顯改善。

本文先整理安裝成本、限制與建議設定,再記錄我試錯的過程。

本文測試基於 h3.c commit 03cb133。專案仍在快速開發,讀者使用新版時應以當下 README 與 --help 為準。

先看結論

實測結果

項目本次結果
512×512、22 幀、20 步denoise 32.89 秒,峰值 18.88GiB
576×1024、124 幀每個完整 denoise step 約 59.3 秒;video VAE 約 185 秒
576×1024、輸入 5 秒(124 幀)全 BF16 約 31 分鐘;int8 約 24 分鐘
全 BF16/int8 畫質肉眼看起來細節相近,色調略有差異
VAE tile 實測320px 可見棋盤格狀接縫;改回官方 256px 後明顯改善

系統環境與使用條件

項目本次設定或限制
硬體M5 Pro、64GB 統一記憶體
系統macOS 26.6.1
基本權重下載量約 134GiB
精確 9:16 尺寸576×1024
幀率24fps
合法幀數5 + 17n,例如 5、22、39、56、124
建議工作流先用 22 幀、4 步找構圖,再跑長片

如果你重視 ComfyUI 工作流與較小下載量,可以先看另一篇 ComfyUI 安裝實錄。如果你比較在意可預測的記憶體占用,h3.c 更值得試。

最短安裝路徑

h3.c 需要可用的編譯工具,以及在 PATH 裡的 FFmpeg 與 FFprobe。假設 MiniMax H3 權重位於 ./MiniMax-H3

git clone https://github.com/antirez/h3.c.git
cd h3.c
git checkout 03cb133
make -j8

./h3 --info -d ./MiniMax-H3

--info 仍會讀取 safetensors header 來檢查模型配置,所以必須在權重下載完成後使用;它不會執行完整推理。

先跑一支 22 幀、4 步的短測試:

mkdir -p outputs

./h3 --profile \
  -d ./MiniMax-H3 \
  -p "A red fox walks through snow, realistic fur, soft wind." \
  --width 512 --height 512 \
  --frames 22 --steps 4 \
  --layers 50 --reuse 1 \
  -o outputs/fox-test.mp4

4 步適合確認環境、構圖與 seed,不代表正式畫質。要比較參數時,固定提示詞、seed、尺寸、幀數與 h3.c commit,並把第一次載入成本和後續暖機結果分開記錄。

下載前,先確認 M5 int8 路徑

h3.c 在當時版本會從 Metal 裝置名稱尋找 M5,再嘗試編譯 TensorOps shader:

BOOL m5 = [gpu.device.name rangeOfString:@"M5"].location != NSNotFound;
BOOL wantsTensorOps = m5 && (!nax || !*nax || strcmp(nax, "0") != 0);

沒有權重時,./h3 --info 無法完成檢查。我不想先下載 134GiB 再發現快路徑不能用,因此寫了一支最小探測程式,複製相同的 runtime 編譯路徑,只初始化 Metal:

device.name          : Apple M5 Pro
architecture         : applegpu_g17s
apple GPU family     : 10
supportsMetal4       : YES
recommendedWorkingSet: 51.84 GiB
maxBufferLength      : 38.88 GiB

h3's "M5" name match  : YES
[H3_METAL_HAS_TENSOR=1] compile: OK
int8 TensorOps kernel present: yes

我另外從編譯後的 library 取得 h3_linear_int8_nax_r128_full_k14336,確認 kernel 函式確實存在。這只能證明 shader 與 kernel 可用,完整推理是否真的走到該路徑,仍要用 profile 或實際效能交叉確認。

這個檢查不到 10 分鐘,卻排在 134GiB 下載之前。對這類大型模型,先做便宜的硬體驗證,比下載後再除錯划算得多。

實際要下載多少

README 提到的 37GiB file-backed/reclaimable 只計算執行時的 DiT 常駐量。完整下載還包含 text encoder、video VAE 與 audio VAE;我用 Hugging Face 檔案資訊計算基本模型目錄:

目錄大小
text_encoder62.1GiB
transformer61.7GiB
video_vae9.7GiB
audio_vae0.6GiB
合計約 134.1GiB

只做文字產生影片與首末幀產生時,不需要 Ref2VA checkpoint。先確認自己的用途,不要直接把所有模型目錄一起下載。

怎麼限制下載頻寬

hf download 在我的連線上可跑到 12.3MB/s,約 98Mbps。當時版本沒有直接的速率限制參數;--max-workers 只能改並行數,單一 CDN 連線仍可能吃滿頻寬。

我後來改用 curl --limit-rate 逐檔下載,兩條各 5MB/s 的連線合計約 10MB/s。要注意 --limit-rate 是每條連線的限制;剩最後一個檔案時,兩條並行自然會退化成一條。

curl -C - 可以從既有檔案續傳,但不能直接沿用 hf download 留下的 Xet staging 檔。長時間下載也要另外處理電腦睡眠;我使用 caffeinate -is -w <pid> 綁定下載程序,工作結束後會自動解除,闔蓋仍可能讓下載中斷。

第一輪效能:記憶體差異最明顯

使用 512×512、22 幀、20 步、--layers 50 --reuse 1

階段wall timepeak live storage
Qwen text encoder7.34 秒3.63GiB
DiT 載入與首次 int8 量化21.61 秒18.88GiB
GPU Euler denoise32.89 秒18.88GiB
audio VAE decode1.84 秒0.28GiB
video VAE decode9.28 秒9.45GiB

h3.c README 當時列出的 M5 Max denoise 成績是 19.18 秒;我的 M5 Pro 是 32.89 秒,慢 1.71 倍。這項跨機器數字只供參考,沒有控制完整的 benchmark 條件。

更重要的是,整趟峰值只有 18.88GiB,可用記憶體沒有掉到危險區,也沒有觀察到新的 swap。相較之下,我的 ComfyUI 測試需要靠模型卸載與快取策略避免大量記憶體周轉。

h3.c 單次推理各階段的時間與峰值記憶體

圖 1 h3.c 單次推理的階段性占用。DiT 載入與 denoise 的峰值均為 18.88GiB,其餘模型在各自階段載入與執行。

ComfyUI 與 h3.c 只能做粗略比較

先前的 ComfyUI 小型 benchmark 是 608×352、5 幀、4 步;h3.c 這組則是 512×512、22 幀、20 步:

pixel-stepssampling/denoise
ComfyUI4.28M約 13.5 秒
h3.c115.34M32.89 秒

h3.c 的 pixel-steps 約多 26.9 倍,denoise 時間約多 2.4 倍。不過 pixel-steps 沒有反映 token 化、attention、量化 kernel 與兩個引擎的其他差異,只能用來說明量級,不能當成嚴格吞吐量 benchmark。

跑直式長片前,要先知道的限制

尺寸

寬高都必須是 32 的倍數,總像素不能超過 768 × 1344。若要精確維持 9:16,尺寸必須是 288m × 512m;在上限內實用的選項只剩 576×1024。

608×1056 也合法,但比例是 19:33,比 9:16 寬約 2.4%。平台如何處理非標準比例並不一致,可能裁切、縮放或加邊框。

幀數與 fps

合法幀數是 5 + 17n:5、22、39、56、73、90、107、124……。本文版本固定輸出 24fps;--seconds 5 會向上對齊成 124 幀,也就是 5.167 秒。

只修改容器 fps 會改變播放速度,不會產生新的影格。若要 30fps,必須另外做插幀或其他時間重取樣。

--layers

MiniMax H3 的 DiT 有 50 個 transformer block。h3.c 會依 checkpoint 中的 AdaLN gate 強度排列保留順序,同時保護頭尾層;未使用的層不載入,因此減少 --layers 可以同時降低時間與常駐權重。

這是畫質與速度的權衡。若要比較,至少固定 seed,並檢查人物、構圖、動作與細節是否一起改變。

5 秒直式片的時間成本

576×1024、124 幀時,我量到一個完整 denoise step 約 59.3 秒;512×512、22 幀則是 4.07 秒,相差 14.6 倍。

兩組的空間 token 比例是 2.25 倍,時間 latent 比例約 5.29 倍,總 token 約增加 11.9 倍。兩個測點顯示成本略快於線性增加。

若直接跑 20 個完整 denoise pass,光 denoise 粗估約 19.8 分鐘。相同 576×1024、124 幀下,video VAE decode 又需要約 185 秒;這項成本不受 denoise steps 或 --layers 影響,但仍會隨輸出尺寸與幀數改變。

因此我的實際工作流是:

  1. 用 512×512 或目標比例的短片、22 幀、4 步找 seed 和構圖。
  2. 確認提示詞與畫面後,再切到 576×1024、124 幀。
  3. 最後才提高 steps、layers 或關閉 reuse。

在本文測試的 5 秒直式設定中,即使使用低步數預覽,依各階段實測推算,載入、denoise 與 VAE 合計仍約需 8 分多鐘。這個數字只適用於本文的尺寸、幀數與參數組合。

包成 web 介面時,為什麼要保留互動程序

h3.c 的互動模式會把 prepared DiT、conditioning 與 decoder 留在同一個工作階段。我因此讓 web server 包住常駐程序,省去每次重新呼叫一次性 CLI 的載入成本:

瀏覽器 ──HTTP/SSE──> Python server ──stdin/stdout──> ./h3 互動模式

h3.c 本機 Web UI:左側設定產生參數,右側預覽影片並保留輸出紀錄

圖 2 我替 h3.c 包的本機 Web UI。左側集中尺寸、幀數、品質、seed 與計算精度,右側可預覽影片並查看歷史輸出。

第一支影片花 64.74 秒,第二支 37.69 秒,縮短約 42%。包裝時有 3 個細節:

  • stdout 使用 pipe 時,最後一行完成訊息可能留在 libc buffer;改用 pty 才能及時收到。
  • stdin 若也用 pty,linenoise 會啟用回顯;最後採 stdout 走 pty、stdin 走 pipe。
  • !output 要在互動模式初始化後再送;新程序又會從 video-0001.mp4 開始編號,因此完成後立即用時間與 seed 改名。

seed 可能超過 32-bit 整數範圍,我在 wrapper 裡直接當字串處理,讓影片檔名保留重現構圖所需的資訊。

VAE 接縫:改回官方 256px 後明顯改善

576×1024 的直式影片使用 320px tile 時,畫面會出現棋盤格狀接縫,這類差異直接比較影片就看得出來。

解法:我的實測是把 H3_VAE_TILE_PIXELS 改回官方設定的 256px 後,接縫已有明顯改善。相同高解析度的 5 秒影片在 ComfyUI 沒有這個問題,因此本文把它視為 h3.c 此版的 video VAE 分塊問題。除非有特別需求,我會優先使用 256px。

320px Video VAE tile 輸出中的棋盤格狀明暗接縫

圖 3 320px tile 的實際輸出截圖。大塊區域之間可見規律的明暗差,形成棋盤格狀接縫。

棋盤格狀接縫用肉眼就能看出來。為了進一步追查成因,我也做了數值驗證:H3_PROFILE=1 顯示 320px 設定會切成 2×4;依分塊幾何預測邊界後,有符號行間差也在對應位置量到尖峰。這項分析的用途是把問題定位到 VAE 分塊,不是用分數取代人眼的畫質判斷。

我也試過放大到 512px,以及把線性混合改成 smoothstep,兩者在這次測試中都沒有改善,因此最後採用官方 256px。這也與上游 PR #1 的建議一致。

Video VAE tile 從 320px 改回官方 256px 後,目視接縫明顯改善

圖 4 接縫改善以實際影片的目視比較為準;分塊邊界與行間差只用來協助定位成因。

全 BF16 與 int8 的目視差異

我原本不確定 int8 量化會不會影響影片細節,後來分別用全 BF16 與 int8 產生 576×1024、輸入 5 秒的影片(實際輸出 124 幀/5.167 秒):

計算精度產生總時間
全 BF161859.12 秒(約 30 分 59 秒)
int81439.96 秒(約 23 分 59 秒)

int8 省下 419.16 秒,約 7 分鐘,產生總時間縮短 22.5%。肉眼比較後,兩者的細節看起來差不多,較容易察覺的是色調有一點差異。這是我這次樣本的結果,提供給在意速度與量化畫質的讀者參考。

我會怎麼選

選 h3.c選 ComfyUI
重視可預測的記憶體占用已有成熟的節點工作流
有約 134GiB 儲存空間希望下載量維持約 40GB
想跑 576×1024、124 幀等大工作量主要產生較短、較小的影片
願意確認並調整 video VAE tile 設定需要串接既有前後處理

對我而言,h3.c 的價值是把記憶體從不可預測的系統周轉,變成比較清楚的階段性占用;它沒有讓所有問題消失,只是把除錯焦點從 swap 移到推理設定與 VAE 分塊。

常見問題

M5 Pro 64GB 跑 h3.c 需要多少儲存空間與記憶體?

本文使用的基本 MiniMax H3 權重約 134.1 GiB。在 512×512、22 幀、20 步的測試中,h3.c 峰值記憶體為 18.88 GiB;實際占用仍會隨版本、尺寸、幀數與參數改變。

h3.c 的 Video VAE 棋盤格接縫怎麼修正?

在本文測試的 commit 03cb133 中,576×1024、124 幀影片使用 320px tile 時可見規律接縫;把 H3_VAE_TILE_PIXELS 改回上游採用的 256px 後,目視結果明顯改善。

h3.c 和 ComfyUI 跑 MiniMax H3,應該選哪一個?

h3.c 適合重視記憶體占用可預測性、能接受約 134 GiB 權重下載的人;ComfyUI 適合需要節點工作流、既有前後處理,或希望把模型下載量控制在約 40GB 的人。

參考來源

相關文章