日期2026-10-18 环境B 机Atlas 800IA2, Ascend 910B4, CANN torch_npu 26.x 目标让 WanVideoWrapperkijai/ComfyUI-WanVideoWrapper在 NPU 上跑文生视频一、问题在华为Asecnd NPU 800A2上部署comfyui跑 Wan2.1-T2V-1.3B 文生视频 workflow 时报错。WanVideoSampler 在forward中报File .../wanvideo/modules/model.py, line 248, in rope_apply_3d freqs_i torch.cat([ ^^^^^^^^^^^ File .../torch_npu/csrc/aten/ops/op_api/CopyKernelOpApi.cpp:89 NPU function error: call aclnnInplaceCopy failed, error code is 161002 AclNN_Parameter_Error(EZ1001): tensor 0 not implemented for DT_COMPLEX128, should be in dtype support list [DT_FLOAT, DT_INT32, DT_INT64, DT_FLOAT16, DT_INT16, DT_INT8, DT_UINT8, DT_DOUBLE, DT_COMPLEX64, DT_BFLOAT16, DT_BOOL]二、根因Wan2.1 RoPE 用 complex dtypetorch.polar(ones, freqs)默认输出complex64NPU 算子aclnnCat不支持DT_COMPLEX128NPU 算子支持列表里只有DT_COMPLEX64没有DT_COMPLEX128dtype promotion当多个 complex tensor cat 阶段NPU 上 implicit 提升到complex128超出算子支持范围三、解法monkey patch torch.cat在 WanVideoWrapper 的__init__.py末尾加# NPU compatibility monkey patch: torch.cat on NPU promotes complex64 to complex128 # but aclnnCat does not support complex128. Cast back to complex64 before cat. import torch as _torch _orig_cat _torch.cat def _npu_safe_cat(tensors, dim0, *args, **kwargs): tensors list(tensors) for i, t in enumerate(tensors): try: if hasattr(t, dtype) and t.dtype _torch.complex128: tensors[i] t.to(_torch.complex64) except Exception: pass return _orig_cat(tensors, dimdim, *args, **kwargs) _torch.cat _npu_safe_cat四、为什么这个 patch 起作用在 cat 之前拦截检查每个输入 tensor 的 dtypecomplex128→complex64强制转换NPU 算子能接受complex64不影响其它 dtype其它 dtype tensor 透传不改动只在 WanVideoWrapper 模块加载时执行一次进程内所有torch.cat都受影响包括 WanVideoSampler、VAE、T5、CLIP 等所有调用五、验证打 patch 后重启 ComfyUIimport 时执行 patch跑测试 prompt之前error 161002DT_COMPLEX128 unsupported 之后status: success output: test_1.3b_shot1_00001.mp4 (5.06s, 81 frames, 832x480)六、风险与副作用风险影响缓解修改全局torch.cat影响整个进程已限制在 WanVideoWrapper 模块custom nodeComfyUI 其它流程不动降低 complex 精度complex128 → complex64 有微小精度差RoPE 只用 complex 的角度分量精度损失对最终视觉无感patch 失序其它 custom node 在 WanVideoWrapper 之前 import 并先调用 cat不影响结果patch 在 WanVideoWrapper 加载后立即生效升级 WanVideoWrapper 后 patch 丢失需要重新加在 commit message 里记录 patch 位置七、复现步骤安装 WanVideoWrapper任意版本把上面 patch 追加到/workspace/ComfyUI/custom_nodes/ComfyUI-WanVideoWrapper/__init__.py末尾重启 ComfyUI跑任意 WanVideo workflow八、传到容器内的方法容器内编辑文件常用方法heredoc常被 bash 多层嵌套吃掉引号不可靠base64 传递推荐PATCH_B64$(echo patch content | base64 -w0) docker exec comfyui bash -c echo $PATCH_B64 | base64 -d /path/to/__init__.pydocker cphost 文件 → 容器文件偶尔 race condition 失败直接在容器内写文件最稳docker exec comfyui bash -c cat /path/to/__init__.py EOF ...patch content... EOF九、为什么不用改 WanVideo Wrapper 源码本身可以考虑给 kijai 提 PR 加 NPU dtype 检查但NPU 算子限制是 Ascend 特有WanVideo Wrapper 是社区项目主要跑 NVIDIA改源码需要 fork 维护分支长期成本高Monkey patch 写在__init__.py末尾升级时重写即可十、其它 dtype 问题如果遇到其它 dtypefp64, fp128 等NPU 算子不支持可以扩展 patch_DTYPE_FALLBACK { _torch.complex128: _torch.complex64, _torch.float64: _torch.float32, # 谨慎使用会丢精度 } def _npu_safe_cat(tensors, dim0, *args, **kwargs): tensors list(tensors) for i, t in enumerate(tensors): try: if hasattr(t, dtype) and t.dtype in _DTYPE_FALLBACK: tensors[i] t.to(_DTYPE_FALLBACK[t.dtype]) except Exception: pass return _orig_cat(tensors, dimdim, *args, **kwargs)附错误码速查错误码含义常见原因161002DT_COMPLEX128 unsupportedNPU 算子不支持本次问题207001NPU out of memory单卡 HBM 不够之前多次遇到EZ1001AclNN_Parameter_Error算子参数不合法dtype / shape 错