我把 MiniMax-H3 装进了一张 Intel 显卡——A 卡 N 卡之外的第三条路,附零基础部署全流程

上一篇我在天台上一招 KO 了老板,用的是 5090。这回换个玩法:同一个模型,我把它搬到了一张 Intel 显卡上。
先说结论:能跑,画质一样,速度慢一截。 过程中我还把自己之前下的一个判断给推翻了。
一、先看片:15 秒,三个镜头,一次没剪
一段清晨的高山晨跑:远景是雪山和漫过山腰的云海,两个人沿着碎石小径并肩跑;跑着跑着,草丛边有只受伤的小狐狸;女生先蹲下伸手,男生随后半跪在她身后;最后她用外套把小狐狸裹进怀里,两人的手在衣角碰到一起,抬头对视,笑了。
这条片子是在一张 Intel Arc Pro B70 上生成的。 不是 Nvidia RTX 5090,是那张你在装机清单里基本不会考虑的 Intel 卡。
全部制作成本:
- 三张参考图(两个人 + 一只狐狸的多视图定妆照)
- 三段提示词(全文在第四节,一个字不藏)
- 一张 Intel 显卡跑了 18 分钟
没有配音,没有音效后期。人物的对白、山间的风声、脚踩碎石的声音,都是模型自己"长"出来的。

三张图都是多视图定妆照:人物有面部特写 + 正面 / 侧面 / 背面全身,狐狸有四个角度的坐姿。给 H3 的参考图,视图越全,身份越稳——它要靠这些角度推断出人物在任意机位下该长什么样。
二、为什么要在 Intel 卡上折腾这件事
正常人不会这么干。买张 N 卡,pip install torch,完事。
但有两个现实理由:
第一,B70 有 32G 显存。 这是关键。跑视频模型,显存是第一道墙——你显存不够,再快的卡也跑不起来。同价位段里能给到 32G 的选择不多。
第二,N 卡不是永远买得到。 供货、价格、渠道,这两年大家都懂。多一条能走通的路,就多一份底气。
所以这次的问题很具体:CUDA 生态之外,这套东西到底能不能跑。
我先给出了一个错误答案
老实交代。我最开始的判断是 "跑不了",理由是:
H3 的量化格式叫 ConvRot INT8,负责解量化的库comfy-kitchen 我去翻了它的安装包,里面只有两个编译好的内核文件:backends/cuda/ 和 backends/hip/(HIP 是 A 卡的)。没有 Intel 的。但我漏了一件事——那个库里还有一个叫 eager 的纯 PyTorch 后端,不依赖任何专用内核,能力清单里明明白白列着 dequantize_int8_convrot_weight。跑在 Intel 卡上时,它会自动选中这个后端。
教训:查能力,别数文件。 判断一个库支不支持某个硬件,去问它的能力注册表(
registry.list_backends()),别靠数编译产物。有没有专用内核决定的是快慢,不是能不能。
三、部署:从零开始,六步
先摆机器:
| 部件 | 配置 |
|---|---|
| 显卡 | Intel Arc Pro B70,32G 显存(实测可用 30.3 GiB) |
| 内存 | 96G |
| 系统 | Debian 13 (trixie),内核 7.0(跑在 Proxmox 虚拟机里) |
| 磁盘 | 给模型留 60G 以上 |
第 0 步:确认驱动装好了
Intel 卡跑计算,靠两套东西:内核驱动(xe,新一代 Intel 显卡驱动,内核自带)和用户态运行时(Level Zero + OpenCL)。
# 看内核驱动加载没
lsmod | grep xe
# 看运行时装没装
clinfo | grep "Device Name"
正常应该能看到你的卡名。运行时包是这三个:
apt install intel-opencl-icd libze-intel-gpu1 libze1
我这台的版本是 26.22.38646.4(Intel 计算运行时)+ libze1 1.31.0。版本别太老,B 系列(Battlemage)显卡需要较新的运行时才认得。
第 1 步:Python 环境
Debian 13 自带 Python 3.13。装 venv 的时候有个小坑:
apt-get update # ← 这句别省,包索引过期会 404
apt-get install -y python3.13-venv
python3 -m venv /root/comfy-xpu
踩坑记录:我直接
apt install python3.13-venv报了 404,因为本地包索引是旧的,指向的版本号已经被新版替换了。apt-get update一下就好。
第 2 步:装 XPU 版 PyTorch ← 最关键的一步
Intel 卡在 PyTorch 里叫 XPU(对应 N 卡的 CUDA)。装的是专门的构建版本:
/root/comfy-xpu/bin/pip install torch torchvision torchaudio \
--index-url https://download.pytorch.org/whl/xpu
装完验一下:
python -c "import torch; print(torch.__version__, torch.xpu.is_available())"
# 2.13.0+xpu True
看到 True 就成了。这一步通了,后面基本就是常规操作。
第 3 步:装 ComfyUI 和依赖 ← 这里有个大坑
git clone https://github.com/comfyanonymous/ComfyUI.git /root/ComfyUI
我用的是 ComfyUI 0.30.0。H3 的节点是 core 内置的,不用装自定义节点包(另外有个 ComfyUI-MiniMax-H3-Guide 节点包提供提示词辅助,可选)。
然后是那个大坑。 直接 pip install -r requirements.txt 会毁掉你刚装好的 XPU PyTorch。
原因:requirements 里的 torchsde 和 spandrel 声明依赖 torch>=1.6.0。pip 一看这个泛型要求,转头就去 PyPI 拉了CUDA 版的 torch,把你的 XPU 版覆盖掉。我当时是看到日志里开始下载 nvidia-cudnn-cu13 才发现不对,赶紧掐了。
正确做法是用 constraints 文件把 torch 钉死:
# 先把已装版本钉下来
cat > /root/pin_torch.txt <<EOF
torch==2.13.0+xpu
torchvision==0.28.0+xpu
torchaudio==2.11.0+xpu
EOF
# 装依赖时带上 -c,并排除三个 torch 包
grep -viE "^torch$|^torchvision|^torchaudio" requirements.txt > reqs_notorch.txt
pip install -r reqs_notorch.txt -c /root/pin_torch.txt \
--extra-index-url https://download.pytorch.org/whl/xpu
⚠️ 注意
torchsde要保留——它是 ComfyUI 真正的依赖(采样器要用),不是 PyTorch 本体。我第一次过滤的时候连它一起删了,是错的。过滤条件要写精确:^torch$只匹配 torch 本身。
装完再验一次 torch.xpu.is_available(),确认还是 True。
第 4 步:下模型权重
四个文件,总共 50.22 GiB:
| 组件 | 文件 | 大小 | 放哪 |
|---|---|---|---|
| 扩散模型 | minimax_h3_ref2va_pruned_int8_convrot | 19.53 GiB | models/diffusion_models/ |
| 文本编码器 | qwen3vl_32b_minimax_h3_int8_convrot | 25.28 GiB | models/text_encoders/ |
| 视频 VAE | minimax_h3_video_vae_fp16 | 4.85 GiB | models/vae/ |
| 音频 VAE | minimax_h3_audio_vae_fp32 | 0.56 GiB | models/vae/ |
从 HuggingFace 的 Comfy-Org/MiniMax-H3 拉。建议开 hf_transfer(多线程下载),我这边实测能跑到 32 MB/s:
pip install hf_transfer
HF_HUB_ENABLE_HF_TRANSFER=1 hf download Comfy-Org/MiniMax-H3 --local-dir ...
注意那个 pruned(剪枝版):19.5G 而不是完整版的 31.7G。H3 有约 13B 参数在 AdaLN 分支上,推理时根本用不到,剪掉不影响画质——这也是官方模板的默认选择,不是什么降级方案。
第 5 步:起服务
cd /root/ComfyUI && /root/comfy-xpu/bin/python main.py --listen 0.0.0.0 --port 8188
启动日志里认准这两行:
Total VRAM 32656 MB, total RAM 98304 MB
Device: xpu:0 Intel(R) Arc(TM) Pro B70 Graphics
看到 Device: xpu:0 就对了。想让它开机自启,写个 systemd 单元即可。
四、显存账和速度账:真实数字
显存:50G 的模型怎么塞进 32G 的卡
答案是不塞——ComfyUI 按阶段把模块换进换出,显卡上永远只放当前干活的那一个。这是从 ComfyUI 日志里抠出来的真实记录:
| 阶段 | 显存占用 |
|---|---|
| 文本编码器工作时 | 25,884 MB |
| 换出编码器、换入扩散模型 | 释放 22,899 MB → 装入 19,996 MB |
| 视频 VAE 解码 | 4,966 MB |
| 音频 VAE 解码 | 577 MB |
峰值是文本编码那一段的 约 25.9 GB,30.3 GiB 的可用显存扛得住,但余量不算宽裕。
所以大内存是隐形前提。 换出去的模块要放系统内存里,96G 内存在这套配置里不是奢侈,是必需。显存不够内存凑——这个思路我在讲大语言模型那两篇里说过,视频模型上照样成立。
速度:慢,但可用
| 任务 | 耗时 |
|---|---|
| 608×352 / 39 帧 / 6 步(冒烟测试) | 75 秒 |
| 864×480 / 124 帧 / 20 步(5.17 秒成片) | 约 360 秒 |
| 本文这条 15 秒片(三镜) | 约 18 分钟 |
对比一下:同样是 r2v、同样 20 步,5090 上 5 秒片实测 98.9 秒。B70 慢了大约 3.6 倍。
慢在哪?就慢在第二节说的那个 eager 后端——没有专用内核,走的是纯 PyTorch 回退路径。这不是 Intel 卡本身算力的问题,是生态的问题:量化内核目前只为 CUDA 和 HIP 编译。
这个速度能接受吗? 看你干什么:
- 要快速刷 seed 抽卡——别用,太慢,一晚上刷不了几条。
- 要批量出片、隔夜跑——完全可用。三条 5 秒片 18 分钟,一晚上能出几十条。
- 要给一台闲置的 Intel 机器找活干——很划算,它跟主力 N 卡机器并行跑,互不抢资源。
五、提示词全文(三镜)
用的是 H3 的 六段式 Ref2VA 格式——参考图定"是谁",提示词定"演什么"。这套格式我在上一篇拆过,这里只贴实际用的,格式细节看上一篇第三节。
三镜共用的角色定义(每镜只写该镜真正出现的角色,这点很重要,下面会说为什么):
subject_definitions:
(来自参考图 1,男性角色):光头、戴细框深色眼镜、留短髭须的中年亚洲男性,
面部轮廓清晰,笑起来眼角有细纹。本片中他穿深灰色长袖跑步上衣与黑色运动长裤、灰白色跑鞋。
(来自参考图 2,女性角色):短卷发、圆脸、皮肤白皙的亚洲女性,神情温和。
本片中她穿米白色跑步上衣与深灰色紧身运动裤、浅色跑鞋。
(来自参考图 3,一只红狐狸):橙红色皮毛、白色胸腹与颊部、四肢末端与耳尖为黑色、
尾巴蓬松且尾尖白色,体型偏小,是一只幼年狐狸。本片中它左前腿受伤,行动迟缓。
(场景):清晨的高山草甸,远处是连绵的雪山与流动的云海,
中景是开满淡紫色野花的草坡,一条碎石小径蜿蜒穿过。
说话人 (S1) 为 ,中年男声,音色偏低、语速平缓。
说话人 (S2) 为 ,女声,音色清亮柔和。第一镜(山径 · 只有两个人,没有狐狸):

summary:
[reference generation] 本任务参考 、 的人物外观与 的场景设定,
生成一段清晨山间晨跑的写实电影镜头。本镜头中只有这两个人物,画面里没有任何动物。
detailed_description:
[Shot 1] 真实电影摄影,35mm 胶片质感,清晨柔和的金色侧逆光穿过山谷晨雾,色调温暖治愈,浅景深。
开场为大远景航拍构图:画面上三分之二是连绵的雪山群峰,峰顶被朝阳染成暖金色,
山腰缠绕着缓慢流动的乳白色云海;画面下三分之一是开满淡紫色野花的高山草甸,
一条浅色碎石小径从画面右下方蜿蜒伸向远处山脚。
与 并肩沿小径向远处慢跑,在辽阔的山景中只占画面很小的比例,
两人步伐轻松同步,手臂自然摆动,跑步时肩背有轻微起伏。
小径上除了这两个人以外空无一物,草甸与山径上没有任何动物出现。
野花与草叶在晨风中持续摇曳,云海在远山间缓慢漂移,光线随云影在草坡上缓慢移动。
跑动中 微微侧头看向身旁的 ,语气轻快地说
(S2) [Chinese] 你看那边,云都在山腰上飘。
顺着她的目光望向远山,微笑着回应
(S1) [Chinese] 值了,早起这一趟真值了。
The camera trucks right with large amplitude at slow speed while slowly pedestals down,
revealing the full breadth of the mountain range.
overall_soundscape:
Gentle alpine wind moving through tall grass, distant birdsong at dawn,
the rhythmic crunch of running shoes on loose gravel, light breathing and the rustle of technical fabric.
non_diegetic_music:
N/A第二镜(发现 · 三个角色都在):

detailed_description:
[Shot 1] 真实电影摄影,35mm 胶片质感,清晨柔和的金色侧逆光,暖调,浅景深。
中景构图:画面左侧是碎石小径边缘的草丛,右后方虚化的背景里是被晨光照亮的雪山轮廓。
蜷缩在小径旁的草地上,橙红色皮毛在逆光中透出绒毛边缘光,
左前腿姿态不自然地蜷着,耳朵警觉地立起又放平,湿润的眼睛看向来人,身体因不安而轻微发抖。
从画面右侧跑入,看到小狐狸后立刻放慢并停下,随即缓缓蹲下身,
上半身前倾,右手掌心向上非常缓慢地朝小狐狸伸出,动作轻柔克制,脸上是关切与怜惜的神情。
随后跑入停在她身后半步,看清情况后也单膝跪下,身体微微前倾,
目光落在小狐狸受伤的前腿上,眉头轻皱。
一边伸手一边压低声音说 (S2) [Chinese] 别怕,别怕,我们不伤害你。
看清伤处后低声开口 (S1) [Chinese] 它前腿受伤了,我们得带它下山。
两人都刻意放轻声音,避免惊吓到小动物。草叶在他们身边轻微晃动。
The camera pushes in with small amplitude at slow speed toward the fox,
the background mountains softening into bokeh.第三镜(对视 · 情感落点):

detailed_description:
[Shot 1] 真实电影摄影,35mm 胶片质感,清晨温暖的金色阳光,浅景深,治愈的暖色调。
近景构图,两人并排蹲在碎石小径上,背景是虚化的雪山与流动云海。
双手捧着一件浅色薄外套,动作极轻地把 裹住抱起,
小狐狸起初还在轻微挣动,被裹住后逐渐安静下来,把下巴搭在她的小臂上,耳朵放平,
尾巴垂在外套外侧轻轻摆了一下。
蹲在她右侧,伸出右手替她把滑落的外套边角向上掖好,
两人的手背在外套边缘短暂相触,两人同时微微一顿,抬起头对视,
先露出温柔的笑意, 也回以微笑,随即两人都有些不好意思地移开视线,
低头看向怀里的小狐狸,轻声说 (S2) [Chinese] 它好像不抖了。
看着她,语气温和地接道 (S1) [Chinese] 那我们慢点走,我陪你一起。
抬眼看他,笑着点了点头。晨风吹动她额前的碎发。
The camera pulls out with small amplitude at slow speed while pedestaling up,
framing the two of them kneeling together on the trail with the sunlit snow peaks behind.为什么分三段,而不是一条 15 秒
H3 单次生成的上限是 362 帧 ≈ 15.08 秒,所以一条到底技术上做得到。
但一次生成 = 一个连续镜头,中间没有剪辑点。这个故事有"远景 → 发现 → 对视"的推进,三段需要不同的景别和镜头运动(横移下降 / 缓推 / 拉远升起),一镜到底做不了这种切换。
还有个实际好处:分段能单独重跑。 362 帧一次成片,第 300 帧崩了整条白跑 18 分钟;分三段,重跑一镜也是 6 分钟。这一点在下面立刻就用上了。
一个真实的翻车和它的修法
第一版跑出来,第一镜里小狐狸跟着两个人一起跑——故事还没到"偶遇",狐狸提前出场了。
奇怪的是,那一镜我只喂了两张人物参考图,根本没喂狐狸图。
原因在提示词里:我三个镜头共用了同一份 subject_definitions,里面定义了 <Subject 3> 是只受伤的狐狸;retention_analysis 里还写着"<Subject 3> 出现在 [Shot 1]"。我等于亲口告诉模型:这一镜里有只狐狸。 它照做了。
修法很直白——每一镜只定义该镜真正出现的角色:第一镜的定义里删掉狐狸,场景顺延成 <Subject 3>,retention_analysis 同步改,overall_soundscape 里那句"细微的动物呜咽声"也一并删掉,再补一句"小径上除了这两个人以外空无一物"。重跑那一镜,6 分钟,狐狸没了。
要领:
subject_definitions不是角色表,是"本镜出场表"。 你定义了什么,模型就倾向于画什么——哪怕你没给对应的参考图。多镜头项目里,这个块要按镜裁剪,不能图省事全片共用。
六、几条带走的认识
Intel 卡跑得动这类模型,但生态差距是真的。 能跑,画质没有任何劣化,代价是 3.6 倍的速度。这个差距不在硬件算力,在量化内核只为 CUDA/HIP 编译。等生态补齐,这个差距会缩小;在那之前,Intel 卡适合当"隔夜批量出片"的第二台机器,不适合当交互式抽卡的主力。
判断"支不支持",要查能力不要数文件。 我差点因为安装包里没有 Intel 内核就否掉整件事,实际上纯 PyTorch 的回退后端跑得好好的。没有专用内核决定的是快慢,不是能不能。
装 XPU PyTorch 最大的敌人是 pip 自己。 任何一个声明 torch>=x 的普通依赖,都可能让 pip 把你的 XPU 版换成 CUDA 版,而且装完不报错——直到你发现 torch.xpu.is_available() 变成了 False。用 constraints 钉死,装完复验。
提示词里"多说的话"和"说错的话"一样有害。 那只提前出场的狐狸,不是模型不听话,是我在角色定义里明明白白写了它。生成模型不会替你判断哪些信息是"背景资料"、哪些是"本镜要画的"——你写进去的,它就当成要画的。
我是把视频模型装进 Intel 显卡、然后发现狐狸提前出场了的桑雅。想我了就常来。