h3.c 跑 MiniMax H3 實測:M5 Pro 64GB 記憶體與 VAE 接縫修正
在 M5 Pro 64GB 上用 h3.c 跑 MiniMax H3,整理 134 GiB 權重下載、Metal 建置、效能與尺寸限制,以及 Video VAE 接縫修正。
目錄展開
用 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_encoder | 62.1GiB |
transformer | 61.7GiB |
video_vae | 9.7GiB |
audio_vae | 0.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 time | peak live storage |
|---|---|---|
| Qwen text encoder | 7.34 秒 | 3.63GiB |
| DiT 載入與首次 int8 量化 | 21.61 秒 | 18.88GiB |
| GPU Euler denoise | 32.89 秒 | 18.88GiB |
| audio VAE decode | 1.84 秒 | 0.28GiB |
| video VAE decode | 9.28 秒 | 9.45GiB |
h3.c README 當時列出的 M5 Max denoise 成績是 19.18 秒;我的 M5 Pro 是 32.89 秒,慢 1.71 倍。這項跨機器數字只供參考,沒有控制完整的 benchmark 條件。
更重要的是,整趟峰值只有 18.88GiB,可用記憶體沒有掉到危險區,也沒有觀察到新的 swap。相較之下,我的 ComfyUI 測試需要靠模型卸載與快取策略避免大量記憶體周轉。
圖 1 h3.c 單次推理的階段性占用。DiT 載入與 denoise 的峰值均為 18.88GiB,其餘模型在各自階段載入與執行。
ComfyUI 與 h3.c 只能做粗略比較
先前的 ComfyUI 小型 benchmark 是 608×352、5 幀、4 步;h3.c 這組則是 512×512、22 幀、20 步:
| pixel-steps | sampling/denoise | |
|---|---|---|
| ComfyUI | 4.28M | 約 13.5 秒 |
| h3.c | 115.34M | 32.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 影響,但仍會隨輸出尺寸與幀數改變。
因此我的實際工作流是:
- 用 512×512 或目標比例的短片、22 幀、4 步找 seed 和構圖。
- 確認提示詞與畫面後,再切到 576×1024、124 幀。
- 最後才提高 steps、layers 或關閉 reuse。
在本文測試的 5 秒直式設定中,即使使用低步數預覽,依各階段實測推算,載入、denoise 與 VAE 合計仍約需 8 分多鐘。這個數字只適用於本文的尺寸、幀數與參數組合。
包成 web 介面時,為什麼要保留互動程序
h3.c 的互動模式會把 prepared DiT、conditioning 與 decoder 留在同一個工作階段。我因此讓 web server 包住常駐程序,省去每次重新呼叫一次性 CLI 的載入成本:
瀏覽器 ──HTTP/SSE──> Python server ──stdin/stdout──> ./h3 互動模式

圖 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。

圖 3 320px tile 的實際輸出截圖。大塊區域之間可見規律的明暗差,形成棋盤格狀接縫。
棋盤格狀接縫用肉眼就能看出來。為了進一步追查成因,我也做了數值驗證:H3_PROFILE=1 顯示 320px 設定會切成 2×4;依分塊幾何預測邊界後,有符號行間差也在對應位置量到尖峰。這項分析的用途是把問題定位到 VAE 分塊,不是用分數取代人眼的畫質判斷。
我也試過放大到 512px,以及把線性混合改成 smoothstep,兩者在這次測試中都沒有改善,因此最後採用官方 256px。這也與上游 PR #1 的建議一致。
圖 4 接縫改善以實際影片的目視比較為準;分塊邊界與行間差只用來協助定位成因。
全 BF16 與 int8 的目視差異
我原本不確定 int8 量化會不會影響影片細節,後來分別用全 BF16 與 int8 產生 576×1024、輸入 5 秒的影片(實際輸出 124 幀/5.167 秒):
| 計算精度 | 產生總時間 |
|---|---|
| 全 BF16 | 1859.12 秒(約 30 分 59 秒) |
| int8 | 1439.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 的人。
參考來源
- antirez/h3.c
- h3.c PR #1:Use 256-pixel VideoVAE tiles by default
- MiniMaxAI/MiniMax-H3
- 本文效能與畫質數字均為 M5 Pro 64GB、macOS 26.6.1、h3.c commit
03cb133的單機測試。
相關文章
MiniMax H3 在 M5 Pro 實測:ComfyUI 安裝、M5 Kernel 與 64GB 記憶體調校
在 M5 Pro 64GB 上用 ComfyUI 跑通 MiniMax H3,整理模型下載、PyTorch nightly、M5 Metal Kernel、啟動參數與記憶體調校實測。
在 Mac 上查 SSD 健康與用量:怎麼查、怎麼看,以及 swap 會不會磨壞硬碟
用一行指令查 Mac 內建 SSD 的累計寫入量與健康狀態,帶你看懂 SMART 報告裡的關鍵欄位,並釐清 swap 對 SSD 壽命的實際影響。
提示詞快取失效解析:系統提示詞多一行日期,本機模型就重新預填
拆解本機模型的預填與前綴快取:為什麼系統提示詞多一行日期,就讓 250k context 的工作階段重新預填 20 分鐘,以及提示詞該怎麼排版才能穩定命中快取,並對照 Anthropic 商業 API 的快取規則。