MiniMax-H3 自建短剧:NVFP4 必须配 Cache-DiT

一部 93 镜的 9:16 竖屏短剧,从 48GB L40S 换到 96GB Blackwell:七轮单变量对照把单镜耗时从 853.9 秒压到 306.9 秒。NVFP4 单独用比 BF16 还慢 17%,配上 Cache-DiT 才拿到 2.8 倍端到端。全部脚本与原始记录已开源。

zhuermu··16 分钟
MiniMax H3AI 视频sglangNVFP4Blackwell自建推理成本核算

先说结论: 在一张 96GB 的 Blackwell 上,把开源音画同出模型 MiniMax-H3 调到能排正片的档位,用的是三个杠杆叠加——NVFP4 权重、SageAttention 2、Cache-DiT。单镜耗时从 853.9 秒压到 306.9 秒(2.8×),显存从 87GB 降到 52GB,100 镜一晚跑完、0 系统失败。但这三个杠杆里最反直觉的一条是:NVFP4 单独用比 BF16 还慢 17%,它的价值必须靠 Cache-DiT 才能兑现。适合谁:要批量出片、且愿意自己扫推理参数的人。不适合谁:一天出 1–2 集的,用官方 API 更省。

实验卡 —— 测试时间: 第一阶段 2026-09-05 ~ 09-13,第二阶段 2026-09-14 ~ 09-15。模型/版本: MiniMax-H3(Community License),第一阶段用 Comfy-Org 重打包的 INT8 剪枝权重 + ComfyUI eb35786 (v0.34.0),第二阶段用社区量化的 NVFP4 权重 + sglang 0.5.19 / torch 2.13 / CUDA 13.0。测试环境: AWS g6e.4xlarge(L40S 48GB,实际可用 46,068 MiB)与 g7e.8xlarge Spot(RTX PRO 6000 Blackwell 96GB),均在 ap-northeast-1;零入站安全组、无 SSH key、全程 Systems Manager 进机。代表性作业: 768×1344、158 帧(6.58 秒)、3 张参考图、seed 1101。实际支付: 自费。第一阶段账单约 $126(其中 $67 是全片跑完后忘停机的 22.4 小时空转),第二阶段 Spot 约 7 小时。两阶段 GPU 时间约 9.5 小时,人时约 14 小时。无赞助、无返佣链接。

全部部署脚本、排障微基准、批跑器,以及 R2–R7 七轮对照与 100 镜生产的原始记录 JSON,都在配套物料包里:github.com/zhuermu/minimax-h3-short。本文出现的每一个数字都能在那里的 data/ 目录溯源。

最终成片(93 镜 / 470.7 秒,9:16 竖屏)在这里:youtu.be/6X4ZuiWXiwQ。下面每一个”多出一台电视""前景自造一张床”的问题,都可以对着它看。

两阶段路线图:第一阶段在 48GB L40S 上算清成本盈亏线并立下制作规范,三个决定把它接到 96GB Blackwell 的生产档

图 1:第一阶段在 48GB 上算清了账、立下了规范;换卡、换框架、换链路这三个决定把它接到 96GB 的生产档。

一、引子:快的那一版不能用#

一周前我已经在 48GB 的 L40S 上把这部剧的横屏版跑出来了:93 镜、535 秒成片、95.6 分钟生成完、0 失败,单帧只要 0.45 秒。按任何一张速度表看,这都是漂亮的数字(那一阶段的完整记录在《AWS g6e 自建 MiniMax H3:10 个坑、性能实测与成本对比》)。

然后逐镜看了一遍,14 镜有缺陷,而且是三类硬伤叠在一起:

  • 身份漂移。 人物脸从第三镜开始一镜一镜地漂,到第十镜妈妈已经不是定妆照上那个人。
  • 硬字幕污染。 生成画面里嵌着我们没要过的字幕。
  • 静音洞。 有对白的镜头之外全是数字静音——24 镜完全没有 room tone,34 处同场景切点电平断崖超过 18dB。

母版剪不出一版能发的片子。于是有了第二阶段:换一张 96GB 的卡,换推理框架,换生成链路,改竖屏重做。第一次估算 21.5 小时,实跑 6.71 小时。

两个阶段之间有一条被反复验证的方法论,也是这篇文章真正想说的东西:官方 spec 里的数值是训练值,推理档要自己扫。 后面每一个反直觉的结论都是这句话的一个实例。

二、48GB 上算出来的账:盈亏线在每 GPU 小时 37.6 秒#

第一阶段最值钱的产出不是那条片子,是一笔账。

东京 g6e.4xlarge 按需 $4.357/h(2026-09-07 Price List API 口径;同机型 us-west-2 是 $3.0042,跨区差 45%),折 $0.000834 / GPU 秒。MiniMax 官方 API 768P 是 $0.08 / 成片秒。

场景自建 g6e 按需官方 API倍数
5.17 秒纯 T2V160 s = $0.133$0.4143.1×
10.12 秒 + ControlNet500 s = $0.417$0.8101.9×
83 秒翻拍成片1.33 h = $4.0$13.33.3×

按纯计算时间看自建便宜 2–3 倍。但 GPU 是按小时计费的,所以真正的口径是每 GPU 小时必须产出 37.6 秒成片才追平 API。T2V 满负荷能出 116 s/h,也就是 32% 利用率打平;带 ControlNet 只有 73 s/h,要 52%。而我那次 8.5 小时的开机里只有 3 小时在生成。

整个第一阶段账单约 $126,其中一次 22.4 小时的开机($67)发生在全片生成结束之后——忘了停机。自建 GPU 的成本不在单价,在利用率和停机纪律,这条在第二阶段依然成立:R7 把每 GPU 小时产出抬到约 77 秒可交付成片,盈亏线随之下移,但一次忘停机就能抵掉一整部片子的生成费。

这和我之前算即梦 Seedance 2.5 的会员积分账是同一个思路:单价不重要,每一秒可交付成片的实付成本才重要。返工率和空转都要算进去。

ComfyUI 教给我的三件事#

第一阶段用 ComfyUI,因为 Comfy-Org 的重打包权重和官方节点是当时最快能跑起来的路径。它教了我三件后来直接决定换框架的事:

1. 负面提示词根本不参与计算。 官方节点图里 negative 走 ConditioningZeroOut,cfg 固定 1.0。这意味着你写在负面里的东西被置零,而你为了”否定”某个物件在正向里提到它,等于把它请进画面——no subtitles 这句话是召唤字幕的。这条在第二阶段的 sglang 链路上同样成立,所以后面所有提示词都改成只描述终态、逐件点名该有的东西。

2. aimdo memory compile error 不是 OOM。 编码器 25.9GB + 主干 20GB = 41.7GB,再加 2.2GB 的 ControlNet 就报这个错。看着像显存不够,实际是 ComfyUI 新的显存编译器不支持某些算子组合;加上 --disable-comfy-compiler 之后峰值反而降到 28GB。

3. 版本必须 pin。 bootstrap 脚本开机 git pull --ff-only,某天拉到了一个读 graph.rogue_count 的 commit,而 comfy-aimdo wheel 没同步升级,KSampler 在 prefetch 清理阶段稳定崩溃(跑到 118 秒)。锁在 eb35786(v0.34.0)才安静。

还有一条工程习惯:接一台 ComfyUI 之前先 curl /object_info 拿准确的节点类名和输入定义。凭常识猜 MiniMaxH3Sampler 这种名字提交,得到的是 400 和一屏 node_errors

顺带一个”官方数值是训练值”的早期证据:48GB 上唯一不糊的档是 ref2v_turbo_4step LoRA + sigma shift 12/3 + 4 步。同镜同 seed 对照官方推荐的 8step v1.0 + shift 6 的 6/8 步变体,4 步版 Laplacian 清晰度 46.6,8 步各变体只有 29–40,而且 4 步是唯一不生出重复人物的配置。分辨率从 1344×768 推到 1920×1088 反而更软(17.1 vs 25.7)——因为 turbo LoRA 的训练分辨率就是 1344×768。

三、三个决定:为什么换卡、换框架、换链路#

9 月 5 日原计划就是 g7e(RTX PRO 6000 Blackwell,96GB),9 个 Region 逐 AZ run-instances 全部 InsufficientInstanceCapacity。配额充足、同 AZ 起 t3.micro 成功,判定是真实容量短缺而不是账户问题;挂了个一分钟轮询一次的 hunt-capacity.sh,一整天全空,只好退到 48GB。9 月 14 日东京终于拿到 g7e.8xlarge Spot。

三个决定其实在第一阶段的失效清单里已经写好了:

换卡,因为要做 BF16 的 A/B。 48GB 上的”软”到底来自 INT8 量化还是 turbo 蒸馏,说不清;只有装下 BF16 全量才能拆开。实测 H3 BF16 在 158 帧 768×1344 峰值 86.9GB、260 帧 92.3GB,80GB 的卡出局。Blackwell 还带来两样 Ada 没有的东西:sm_120 原生 FP4 tensor core,以及 SageAttention2 的 sm_120a 目标架构。这一点在第一阶段有过直接对照——L40S 是 Ada 架构,加载 NVFP4 权重时日志里明明白白写着 Emulated ops: mxfp8, nvfp4,软件模拟,比 INT8 还慢。

换框架,因为三个杠杆都在 sglang 里。 sglang 0.5.19 用 --model-variant 一键切分区,/v1/videos 是服务化接口,Cache-DiT / SageAttention / NVFP4 三个加速手段在同一个框架里;并且 0.5.19 已经合入了 sm_120 上三个关键补丁(FP4 标度分支、qkv per-row scale 随行重排、attention selector 全局回退)。这三个补丁缺任何一个,NVFP4 都会静默出灰糊片——我在装机前逐个对着源码核过。

换链路,因为身份要从源头锁。 第一阶段用 I2VA/FL2VA 首尾帧接力,上一镜的尾帧当下一镜的首帧,误差逐镜叠加;更糟的是当上一镜尾帧是无人的空场景(人走出画、门关上),模型会自由发明下一镜入画人物的长相。ref2va 是纯多参考图分区:每镜独立喂定妆图和场景图,不挂首尾帧,不从上一镜继承任何东西。身份、人数、配饰级细节从此稳住,代价是景别、曝光、道具位置只能靠提示词软约束——后面制作侧的坑几乎都出在这个代价上。

画幅顺手改成竖屏 768×1344,按短视频平台交付。

四、七轮单变量对照#

控制变量:镜头 S001,158 帧(6.58 秒),768×1344,seed 1101,3 张 role=reference 参考图(妈妈定妆、女主定妆、卧室场景),flow_shift 12 / audio_flow_shift 3,请求里不传 quality 字段。所有时间是 /v1/videos 提交到 completed 的墙钟时间。

七轮单变量对照的耗时与显存对比:NVFP4 单用比 BF16 更慢,配上 Cache-DiT 才拿到 2.8 倍

图 2:七轮单变量对照。NVFP4 单用(R4/R6)比 BF16 还慢,配上 Cache-DiT(R7)才拿到 2.8×。

权重AttentionCache-DiT耗时 ss/步峰值显存人工核对
R2BF16SDPARDT0.12 W450853.917.486.9G基线,身份/人数通过
R3BF16SDPARDT0.16 W430562.619.286.9G细节略降,内容不变
R4NVFP4sage20457.422.248.6G多出第二台 CRT
R5BF16SDPARDT0.16 W220356.815.386.9G一台 CRT
R6NVFP4sage30688.522.448.6G一台 CRT;色偏
R7NVFP4sageRDT0.16 W230306.99.3352.5G一台 CRT;同 R6 色偏

R2 基线。 一个 6.6 秒的镜头要 14 分钟,93 镜 14,320 帧外推 21.5 小时。身份和人数这两个致命项在第一镜就过了——这是 ref2va 的功劳,不是步数的。

R3:减步数、抬阈值,单步反而更慢。 50 步降到 30 步,Cache-DiT 残差阈值 RDT 从 0.12 抬到 0.16,本意是让缓存更容易命中,结果平均单步从 17.4 秒涨到 19.2 秒。原因有两条:WARMUP=4 在 30 步里占 13.3%(50 步里只占 8%),这几步不缓存;步数一少,相邻步的残差差异变大,更难触发阈值。缓存白开了还付了 warmup。教训:步数减少时 WARMUP 要同步减。

R4:上 NVFP4 + SageAttention,显存砍一半,画面多了一台电视。 20 步,显存从 86.9GB 降到 48.6GB——这是 NVFP4 最确定的收益。但画面右侧多出了第二台 CRT 显示器,一个”合理但不存在”的物体。

R5:WARMUP 降到 2,缓存第一次真正命中。 BF16、20 步,单步 15.3 秒,首次低于无缓存的 17.4 秒。到这里 BF16 + Cache-DiT 已经是一个可用的生产档:单镜 356.8 秒,93 镜约 9 小时。

R6:NVFP4 30 步,比 BF16 还慢 17%。 同 30 步,R6 单步 22.4 秒,R3(BF16)19.2 秒;而且和步数无关——R4 的 20 步也是 22.2 秒/步。好消息是第二台 CRT 没有复现,判定为 NVFP4 × 20 步的交互:量化误差加步数不足,叠加起来收敛到多物体。NVFP4 不要低于 30 步。

慢在哪?我在这张卡上单独量了两个内核(脚本在物料包 scripts/diag/):

  • SageAttention2 对 Torch SDPA,H3 真实序列长度 41,456,136 ms → 80 ms,1.70×
  • FlashInfer 的 FP4 GEMM 对 BF16 cuBLAS,四个 DiT 线性层形状合计,78.9 ms → 22.0 ms,3.58×

两个内核都达到了文档水位。那 28% 的差额在胶水层:sglang 的 ModelOptFp4LinearMethod.apply 在每个 linear 前都要对激活做在线 fp4_quantize——算 global scale、量化、按 swizzled layout 重排——M=41,472 的大张量,每个 block 4 次,52 个 block,每一步都来一遍。这是逐层的固定开销,不随步数变,吃掉了 GEMM 的全部收益还有余。

单步耗时分解:NVFP4 的额外开销在每层的在线激活量化,而 Cache-DiT 整块跳过 block 时把这份开销一起省掉

图 3:单步耗时分解(柱高为实测,分段比例为推断)。NVFP4 慢在逐层的在线激活量化,而这正是 Cache-DiT 整块跳过时一起省掉的部分。

R7:NVFP4 + sage + Cache-DiT,单步 9.33 秒。 同样的缓存参数(RDT 0.16 / WARMUP 2 / MC 2)放到 NVFP4 上,单步从 22.4 秒降到 9.33 秒,2.4×;而在 BF16 上它只省了 12%(17.4 → 15.3)。

解释就在上一段:Cache-DiT 的 DBCache 是整块跳过 transformer block——相邻步残差差异低于阈值时,这个 block 的所有计算都不做,复用上一步的结果。跳过整个 block 时,block 里所有 linear 的在线量化开销也一起跳了。NVFP4 慢的那部分,恰好是缓存最擅长绕开的部分。

核心结论:NVFP4 和 Cache-DiT 是强互补。 单用任何一个都不如 BF16 + Cache-DiT,两个一起用才拿到 2.8× 的端到端。所以”FP4 GEMM 快 3.58ד和”端到端慢 17%“可以同时为真——别单独评测 NVFP4。

R7 相对 R5 快 14%,还多跑了 10 步(更少的”多余物体”类收敛失败),52.5GB 的显存给了跑 345 帧长镜的余量。代价是 NVFP4 两轮(R6/R7)相对 BF16 有一致的色偏:更暗、饱和更高、额头纹理更重、脸略窄。因为全片统一用 R7,色偏在片内一致,后期一次调色抵消;混用 BF16 和 NVFP4 镜头才会跳色。R7 定为生产档。

顺带一条跨阶段的参照,用来说明速度表怎么读:第一阶段横屏的 0.45 s/帧看着比 R7 的 1.94 快 4 倍,但那是 1024×576、4 步 turbo、INT8 剪枝,出的是”能看”不是”能交付”。要比只能比每 GPU 小时可交付成片秒数:第一阶段约 334 秒不可交付,第二阶段 77 秒可交付。另一个差别是标度:第一阶段单帧成本随帧数超线性(ControlNet 下 124 帧 1.6 s/帧到 345 帧 2.7 s/帧),第二阶段 sage + cache 下 158 帧到 260 帧只从 5.40 走到 5.54,注意力被摊平了。

五、让第三方 NVFP4 权重跑起来#

官方没有发 FP4 权重。我用的是社区量化的 MiniMax_H3_Ref2VA_nvfp4_mixed.safetensors(24.4GB,线性层 NVFP4,部分 INT8/INT4,adaln 保留 FP8)。这是 Comfy 转换器导出的布局,sglang 0.5.19 的 loader 把它识别成原生 ModelOptFp4Configqkv / o_proj / fc1 / fc2 绑到 ModelOptFp4LinearMethod,走 FlashInfer 的真 FP4 GEMM——我用探针脚本逐层核过,不是反量化路径。

两处要动手修:

文件尾部有 65 字节垃圾。 转换器附加了一行文本标记(L2P_bypass_..._),safe_open 直接报错,截掉即可。

50 个 adaln 层缺元数据。 loader 报 missing comfy_quant metadata:这些层是 FP8 裸 cast,没有 weight_scale。修法是给每层补一个 scale=1.0 的标量和 float8_e4m3fn 格式标记,40 行 Python(scripts/deploy/fix_adaln_markers.py)。修完的格式集合(nvfp4 208 层 + float8_e4m3fn 50 层)落在 loader 的允许列表内。

SageAttention 2 要源码编译:PyPI 上只有 1.x(纯 Triton INT8 QK),2.2.0 的 kernel 在 thu-ml 的仓库里。TORCH_CUDA_ARCH_LIST=12.0 出 sm_120a cubin,24 核约 30 分钟。全局启用 sage 时,text_encoder / video_vae / audio_vae 必须显式回退 torch_sdpa--component-attention-backends),否则起服务直接 ValueError

三条”日志比文档可信”#

  • sglang 随包手册写着 SageAttention is rejected for the current packed multi-segment attention,但 H3 的代码里没有任何拒绝判据,上游 cookbook 已经改成”装依赖 + 加 --attention-backend sage_attn”——手册是陈旧文本。
  • --attention-backend fa 在 sm_120 上会被静默降级回 SDPA,所以每次切配置都要从服务日志回读实际后端。
  • 请求里带 quality 字段会把 Cache-DiT 整个关掉,而这个字段的默认值看起来完全无害。

六、100 镜实战:先把分镜压紧#

100 镜生产流水线:提示词与参考图经 S3 上行,Systems Manager 远程起批,成片逐镜同步下行,本地三帧验收

图 4:100 镜生产流水线。提示词与参考图经 S3 上行,Systems Manager 远程起批,成片逐镜同步下行,本地三帧验收。

第一阶段就发现 H3 的 5.17 秒是训练下限:短句说完画面就静止,32% 的时间在空转。第二阶段直接改分镜:每镜时长 = 台词字数 ÷ 4.2 + 1.2 秒反应,上取到 17k+5 帧网格(可用最短档 107 帧 / 4.46 秒)。两句台词的镜拆成两镜(每镜一个发声人本来就是规范),但四对一口气的短句(“窃玉……偷香!“这种语气)保持合并;唯一一条 14.4 秒的巨蛇长镜拆成”现身 / 逼近”两段;两条动作链镜保留长度。

93 镜 14,320 帧变成 100 镜 11,975 帧,总帧数少 16.4%。实测成本严格线性于总帧数,所以这 16.4% 直接就是 GPU 时间。短镜的另一个收益在质量:漂移少、幻觉物体少、一镜重做只赔 5 秒不赔 15 秒。

P1 批次:6.71 小时,100/100,0 失败。 100 份六段式提示词(86 份由脚本从竖屏 V1 转换,14 个拆分镜手写)结构检查全过;批跑脚本可续跑、每镜完成即同步 S3、失败只记录不重试、seed = 基数 + 序号。19:43 启动,凌晨 02:25 完成,402 分钟,平均 2.02 s/帧,峰值显存 59.3GB(260 帧长镜)。

一个排期时直接能用的模型:单帧耗时和参考图数量线性相关——1 张 1.06、2 张 1.53、3 张 2.08、4 张 2.66 s/帧。参考图作为 dense token 进了序列,这就是 ref2vat2va 慢的全部原因。

成片交付前还要过一遍码率和存储的账,竖屏 470 秒的成片按什么档位转出、CDN 上要花多少流量,我用自己的视频码率 / 带宽 / 存储估算器算,不再手算。

中帧总览 99/100 通过——然后用户给了 16 条缺陷#

100 镜中帧拼成四张 5×5 总览,逐格看:身份对、人数对、无字幕、无多余物体,99 镜一次过,1 镜重做。

然后逐镜看视频,拿到 16 条缺陷:多出一只手臂、手指变形、女主说话没朝着妈妈、该另一个角色说的话给了女主、背弟弟的手抓在自己肩上而不是托着腿、静默听者半边脸在笑、巨蛇舌头穿过窗栏、女主整个变形和脚交织在一起。

只看中帧会漏掉的东西:尾帧脸出画、多出的手臂、手指数量、说话人朝向、表情。 之后所有验收改成首/中/尾三帧放大目检,报告口径写”中帧初检”,不写”通过”。

三个最有代表性的制作侧问题#

1. 参考图的影棚灰底漏进车站场景(S015)。 女主定妆图是灰色影棚底,模型把它当成了场景。修法是把车站场景图提到 <Picture 1> 的位置、正文明确”车站路面、无影棚背景”。更根本的做法是预处理定妆图,把灰底换成透明或与场景同色系。

2. 场景图里沙发是空的,模型三次都在前景”自造一张床”(S070)。 剧情是女主睡在客厅沙发上,巨蛇从窗外探头。场景参考图里沙发在中景、空着。第一版把女主放到了镜头前一块不存在的床面上;提示词加了”她直接躺在沙发上、前景没有其他床面”,第二版沙发上多了一个盖毯子的女主,前景床面上还躺着一个。

S070 的两次失败:左图女主被放到前景一块不存在的床面上,右图加了否定句后沙发和前景各出现一个女主

图 5:S070 两次失败。左:女主被放到前景一块不存在的床面;右:加了否定句后沙发和前景各出现一个女主。

否定句加到这个程度都压不住——ConditioningZeroOut 的教训在这里以另一种方式重现:你提到了床,它就画床。

最后有效的修法不是再改一句话,而是在前景放一个场景里已有的实物:场景图里本来就有木茶几和果盘,让镜头越过茶几拍沙发上的女主。前景被茶几占住,模型没地方再造床。一次通过。

S070 通过版的首中尾三帧:镜头越过木茶几拍沙发上的女主,前景被实物占住

图 6:S070 通过版的首/中/尾三帧。镜头越过茶几拍沙发上的女主,前景被实物占住,模型没地方再造床。

给模型一个实物填掉它想填的空间,比告诉它”不要放东西”有效。 这和第一阶段”身份与影调靠图锁,不靠字”是同一件事。

3. 静默听者的半脸表情压不住(S030B)。 弟弟半张脸在画内,剧本要委屈,出来是笑,换 seed 不稳。修法是让他的脸完全出画,只留后脑和白色衣肩——他本来就是静默听者,表情问题从构图上消失了。

补生成纪律#

19 镜、4 轮、56 分钟 + 三次小批。规则是:每镜重生成一次就停下汇报,不自动第三次;每轮用独立的 seed 段避开前几轮;配置全程不切换,避免 BF16 与 NVFP4 混出色偏;三个”前后镜难以对上”的镜合并成一镜生成(店家抢手机、起身腿麻、妈妈两句连说),一次采样内站位和视线自洽。最后又在剪辑上砍掉两段无意义剧情和两个手部插镜,成片 93 镜、470.7 秒——就是这一版

七、三条带走的东西#

1. Blackwell 上 NVFP4 的价值要靠 Cache-DiT 兑现,别单独评测它。 单用 NVFP4 比 BF16 慢 17%,慢在每层的在线激活量化;Cache-DiT 整块跳过 block 时把这份开销一起跳掉,2.4× 就出来了。评测报告里”FP4 GEMM 3.58ד和端到端”慢 17%“可以同时为真。

2. 日志比文档可信,官方数值是训练值。 手册说 sage 不支持,源码里没有拒绝判据;quality 字段静默关缓存;fa 后端静默降级;Cache-DiT 默认 WARMUP=4 在 30 步内等于没开;turbo 官方 8 步比 4 步糊。每次切配置回读日志,每个推理参数自己扫一遍。

3. 视频模型的构图先验很强,用实物占位比用否定句有效。 参考图锁身份,场景图锁环境,前景实物锁空间;提示词只描述终态。

以及那条从第一阶段带过来、第二阶段依然成立的账:自建 GPU 的成本不在单价,在利用率和停机纪律。

没做完的: Cache-DiT 支持按请求 extra_body 传参,同一次开机内扫 RDT 0.24 还没做;NVFP4 胶水层那 28% 的 profiler 定位没做,做掉了 R7 还能再快;Turbo LoRA 与量化权重不能靠 --lora-path 共存,必须先在 BF16 上离线合并再量化,这条离线流水线没走通;NVFP4 52GB 下的两路并发没试。

许可提醒: MiniMax-H3 是 Community License,不是 Apache/MIT,申请表标注了地区限制,商用前请自行确认。NVFP4 权重是第三方社区量化,本文修改了它的元数据,不代表官方精度。

八、物料包:脚本、微基准和原始记录#

仓库在 github.com/zhuermu/minimax-h3-short,按用途分三块:

目录内容
docs/两阶段实验记录、机型与模型选型、R2–R7 对照、部署与服务配置、NVFP4 排障判断树、生产运行与制作问题
scripts/deploy/01_setup_env.sh(uv + sglang 0.5.19 + SageAttention2 源码编译 sm_120a)、02_dl_nvfp4.shfix_adaln_markers.py、三份 systemd 服务脚本与互斥切换的 switch_serve.shcomfyui_g6e/ 是第一阶段的 48GB 路线
scripts/diag/probe_quant_method.py(判定量化层实际绑定的内核路径)、fp4_gemm_bench.py(FlashInfer mm_fp4 vs cuBLAS,用 H3 真实形状)
scripts/batch/ scripts/prompt/ scripts/post/可续跑批跑器、紧凑分镜与六段式提示词转换器、首/中/尾三帧验收条与无重编码粗剪
data/R2–R7 七轮与 P1 100 镜的原始记录 JSON、样例提示词的修法前后版本、第一阶段的事实清单(逐条标注来源)

96GB 卡上的复现最短路径:

# GPU 机(Amazon Linux 2023, sm_120, ≥96GB 显存, ≥500GB 盘)
bash scripts/deploy/01_setup_env.sh                 # ~1 h
bash scripts/deploy/02_dl_nvfp4.sh                  # ~30 min,可与上一步并行
sudo bash scripts/deploy/switch_serve.sh nvfp4-cache   # 起 R7,等 /health 200
#   起来后一定回读日志:要看到 DBCache_...R0.16,否则缓存没生效

# 本地:任务表.json + prompts/ + refs/ 打包传 S3,再远程起批
S3=s3://bucket/prefix RUN=/home/ec2-user/p1 bash scripts/batch/start_remote.sh

仓库不含成片视频与人物参考图(版权和体积),帧图只作验收样例;NVFP4 权重也不在里面,只有下载与修复脚本。

本文所有数字来自我自己付费的两次开机,没有赞助方,也没有返佣链接。文中观点仅代表个人,与雇主无关。

参考资料

  1. MiniMax-H3 模型仓库 — MiniMax AI on Hugging Face
  2. MiniMax H3 Community License — MiniMax AI on Hugging Face
  3. Comfy-Org 重打包的 MiniMax-H3 权重 — Comfy Org on Hugging Face
  4. 社区量化的 NVFP4 权重(非官方) — Abiray on Hugging Face
  5. sglang 推理框架 — GitHub · sgl-project
  6. Cache-DiT:DiT 的块级缓存加速 — GitHub · vipshop
  7. SageAttention 2 — GitHub · thu-ml
  8. FlashInfer(FP4 GEMM 内核来源) — GitHub · flashinfer-ai
  9. 成片:93 镜 / 470.7 秒,9:16 竖屏 — YouTube
  10. 本文配套物料包:部署脚本、微基准、批跑器与原始记录 — GitHub · zhuermu/minimax-h3-short
  11. Amazon EC2 G6e 实例 — AWS

常见问题

自建 MiniMax-H3 需要多大显存?
看你要什么。48GB 的 L40S 只能跑 INT8 剪枝主干 + INT8 文本编码器,出的是「能看」不是「能交付」。BF16 全量在 158 帧 768×1344 下峰值 86.9GB、260 帧 92.3GB,所以 80GB 的卡也不够,96GB 才是最小舒适区。上了 NVFP4 之后峰值降到 52.5GB,但要先有一张能原生跑 FP4 的 Blackwell。
NVFP4 量化到底能不能提速?
单独用会更慢。我实测同 30 步下 NVFP4 + SageAttention 是 22.4 秒/步,BF16 是 19.2 秒/步,慢 17%。微基准里 FP4 GEMM 相对 cuBLAS 是 3.58×、SageAttention2 相对 SDPA 是 1.70×,两个内核都没问题——差额在框架胶水层:每个线性层前都要对激活做在线 fp4_quantize,这是逐层固定开销。加上 Cache-DiT 整块跳过 transformer block 之后,这份开销一起被跳掉,单步从 22.4 秒降到 9.33 秒。
Cache-DiT 的参数该怎么设?
别用默认值。文档默认 WARMUP=4、RDT=0.04,在 30 步档位下 warmup 占 13.3%,加上步数少时相邻步残差差异变大、更难命中阈值,结果是缓存白开还付了 warmup 成本。我最后的生产档是 RDT 0.16 / WARMUP 2 / MC 2,30 步。规律是步数减少时 WARMUP 要同步减。另外请求里带上 quality 字段会把 Cache-DiT 整个关掉,而这个字段看起来完全无害。
自建 GPU 比调官方 API 便宜吗?
按纯计算时间算便宜 2–3 倍,但 GPU 是按小时计费的。用我 2026-09-07 记录的东京按需价 $4.357/h 折算,每 GPU 小时必须产出 37.6 秒可交付成片才追平 API 的 $0.08/秒。我那次 8.5 小时开机里只有 3 小时在生成,而且有一次忘停机跑了 22.4 小时、白付 $67。1–2 集/天的产量应该用 API;自建只在批量生产、或者 Spot / Savings Plan 下划算。
为什么生成画面里会出现没要过的字幕和多余物体?
官方节点图里负面提示词走 ConditioningZeroOut、cfg 固定 1.0,也就是负面根本不参与计算。你为了否定某个东西而在提示词里提到它,等于把它请进画面——「no subtitles」这句话本身就是召唤字幕。多余物体是同一件事的另一面:模型的构图先验很强,前景空着它就会填。有效的修法不是再加一句否定,而是在前景放一个场景里已有的实物把空间占住。
分享这篇文章 微博 X LinkedIn
微信扫码

用微信扫一扫,把文章带到聊天或朋友圈。

讨论

用 GitHub 账号评论 —— 评论存放在本仓库的 Discussions 里。

继续阅读