Ascend 910B3 运行 ComfyUI 0.30.2 + MiniMax-H3 INT8 的几个关键适配
最近重新部署了一套 ComfyUI 0.30.2 环境,用于在 Ascend 910B3 上运行 MiniMax-H3 INT8。由于重新创建了 Python 虚拟环境,之前针对 Ascend 做过的部分适配被覆盖,重新踩了一遍几个比较典型的问题。
最终主要解决了三个问题:
- MiniMax-H3 文本编码器加载卡死
- ComfyUI 错误进入 NVIDIA CUDA 判断逻辑
- INT8 矩阵乘法回退 CPU
最终 MiniMax-H3 可以正常加载并使用 Ascend NPU 执行 INT8 计算。
环境
Ascend 910B3
CANN 9.1.0-beta.1
Python 3.13.14
PyTorch 2.12.0+cu130
torch_npu 2.12.0
ComfyUI 0.30.2
comfy-kitchen 0.2.26
启动后 ComfyUI 可以正常识别 NPU:
Total VRAM 62420 MB
pytorch version: 2.12.0+cu130
Device: npu
Using pytorch attention
1. MiniMaxH3TEModel 加载一直卡住
执行工作流后日志停在:
Requested to load MiniMaxH3TEModel_
NPUCachingAllocator.cpp:
The current CANN and Soc versions require processing
for 32 padding size, with memory allocation.
之后没有模型加载进度。
一开始看起来像模型加载很慢,但进一步观察进程发现:
CPU system 使用率约 100%
minflt/s 超过 30 万
磁盘读取 0 KB/s
RSS 基本不变化
NPU 显存基本不变化
这说明并不是正常读取模型,而是进程大量消耗在内核态的 page fault / mmap 处理上。
最终解决方法是在 ComfyUI 启动参数中加入:
--disable-mmap
例如:
ASCEND_RT_VISIBLE_DEVICES=6 \
PYTORCH_NPU_ALLOC_CONF=expandable_segments:True \
python main.py \
--listen 0.0.0.0 \
--disable-smart-memory \
--disable-mmap
加入之后文本编码器可以正常加载:
Requested to load MiniMaxH3TEModel_
loaded completely;
60846.53 MB usable,
25883.83 MB loaded,
full load: True
所以在当前这套 Ascend + ComfyUI 0.30.2 环境中,我最终保留了 --disable-mmap。
2. ComfyUI 错误调用 torch.cuda
文本编码器解决以后,又遇到了:
RuntimeError:
Found no NVIDIA driver on your system.
调用栈最终是:
comfy.ops.pick_operations()
supports_fp8_compute()
torch.cuda.get_device_properties(device)
torch._C._cuda_init()
问题在于当前 PyTorch 是:
2.12.0+cu130
因此:
torch.version.cuda
是有值的。
但这台机器实际运行设备是:
torch.npu.is_available() == True
torch.cuda.is_available() == False
也就是说:
PyTorch 编译信息带 CUDA
≠
当前设备就是 NVIDIA GPU
ComfyUI 的部分设备判断因此错误进入了 CUDA 专属逻辑。
修复 is_nvidia
修改:
comfy/model_management.py
将 NVIDIA 判断增加 Ascend 和 CUDA availability 检查:
def is_nvidia():
global cpu_state
if cpu_state != CPUState.GPU:
return False
if is_ascend_npu():
return False
if torch.version.cuda and torch.cuda.is_available():
return True
return False
同时给 supports_fp8_compute() 增加设备保护:
if device is None:
device = get_torch_device()
if getattr(device, "type", None) != "cuda":
return False
这样 NPU 就不会再执行:
torch.cuda.get_device_properties()
处理后 MiniMax-H3 diffusion model 可以正常加载。
3. INT8 计算回退 CPU
模型加载成功后开始采样:
0%| | 0/20
但出现:
The operator 'aten::_int_mm'
is not currently supported on the NPU backend
and will fall back to run on the CPU.
这个问题对性能影响很大。
原因是 comfy-kitchen 的 eager INT8 路径最终使用:
torch._int_mm()
而当前 torch_npu 没有为:
aten::_int_mm
提供对应的 NPU 实现,因此自动 fallback 到 CPU。
对于 MiniMax-H3 这种大量使用 INT8 Linear 的模型,CPU fallback 会直接导致采样速度大幅下降。
4. 使用 Ascend 原生 npu_quant_matmul
Ascend 本身提供了:
torch_npu.npu_dynamic_quant
以及:
torch_npu.npu_quant_matmul
因此可以直接修改:
comfy_kitchen/backends/eager/quantization.py
在 int8_linear() 中增加 NPU 分支。
核心逻辑:
if x.device.type == "npu":
import torch_npu
x_2d = x.reshape(-1, x.shape[-1]).contiguous()
x_8, x_scale = torch_npu.npu_dynamic_quant(x_2d)
x_scale = (
x_scale.reshape(-1)
.to(device=x.device, dtype=torch.float32)
.contiguous()
)
result = torch_npu.npu_quant_matmul(
x_8.contiguous(),
weight.T.contiguous(),
weight_scale.reshape(-1)
.to(device=x.device, dtype=torch.float32)
.contiguous(),
pertoken_scale=x_scale,
output_dtype=out_dtype,
)
其他设备继续保留原来的:
_int8_matmul_accumulate()
路径即可。
5. 一个容易踩的点:不要重复执行 scale
原来的 torch._int_mm 路径通常是:
INT8 MatMul
→ INT32
→ activation scale
→ weight scale
→ BF16 / FP16
但是:
torch_npu.npu_quant_matmul()
调用时已经传入:
weight_scale
以及:
pertoken_scale=x_scale
所以 NPU 分支执行完成后,不能再执行原来那段手工 scale:
result * x_scale * weight_scale
否则会重复缩放,导致结果错误。
因此代码结构应该明确分开:
if device == "npu":
# npu_quant_matmul
# 不再手动 scale
else:
# 原 comfy-kitchen 路径
# 保留手动 scale
6. 验证 Ascend INT8 算子
可以先单独验证:
import torch
import torch_npu
device = "npu:0"
x = torch.randn(
128,
2048,
dtype=torch.bfloat16,
device=device
)
w = torch.randint(
-127,
128,
(2048, 2048),
dtype=torch.int8,
device=device
)
weight_scale = torch.ones(
2048,
dtype=torch.float32,
device=device
) * 0.01
x8, x_scale = torch_npu.npu_dynamic_quant(x)
y = torch_npu.npu_quant_matmul(
x8.contiguous(),
w.T.contiguous(),
weight_scale.contiguous(),
pertoken_scale=x_scale.reshape(-1).float().contiguous(),
output_dtype=torch.bfloat16,
)
print(y.shape)
print(y.dtype)
print(y.device)
正常输出:
torch.Size([128, 2048])
torch.bfloat16
npu:0
说明 INT8 GEMM 已经真正运行在 NPU 上。
最终启动参数
目前我使用:
ASCEND_RT_VISIBLE_DEVICES=6 \
PYTORCH_NPU_ALLOC_CONF=expandable_segments:True \
python main.py \
--listen 0.0.0.0 \
--disable-smart-memory \
--disable-mmap
正常加载后日志类似:
Requested to load MiniMaxH3TEModel_
loaded completely;
25883.83 MB loaded
Detected mixed precision quantization
loaded completely;
19996.14 MB loaded
并且采样时不再出现:
aten::_int_mm
will fall back to run on the CPU
总结
这次 ComfyUI 0.30.2 + MiniMax-H3 在 Ascend 910B3 上主要涉及三类兼容性问题:
模型 mmap
↓
--disable-mmap
CUDA / NPU 设备判断
↓
避免 NPU 调用 torch.cuda.*
INT8 Linear
↓
torch._int_mm
↓
CPU fallback
↓
npu_dynamic_quant
+
npu_quant_matmul
最终实际运行链路变成:
MiniMax-H3 INT8 Weight
↓
ComfyUI
↓
comfy-kitchen
↓
npu_dynamic_quant
↓
npu_quant_matmul
↓
Ascend 910B3
还有一个值得注意的问题:
comfy-kitchen 的修改位于 Python 虚拟环境:
.venv/lib/python3.13/site-packages/
因此重新创建虚拟环境或者升级 comfy-kitchen 后,这部分 NPU 适配会被覆盖。
最终文生图速度:
默认文生图工作流:
时长:5秒
清晰度:| 0.4 | 16:9 | 864 x 480 |
步长:20
运行时长(第二次):[INFO] Prompt executed in 161.81 seconds
工作流模型配置如下:
鲲鹏昇腾开发者社区是面向全社会开放的“联接全球计算开发者,聚合华为+生态”的社区,内容涵盖鲲鹏、昇腾资源,帮助开发者快速获取所需的知识、经验、软件、工具、算力,支撑开发者易学、好用、成功,成为核心开发者。
更多推荐
所有评论(0)