《TorchNPU FLUX_DVM 编译训练实战:从环境搭建到问题修复》
作者:昇腾实战派知识地图:【昇腾实战派】综合指导知识地图_昇腾大模型地图-CSDN博客
背景概述
在 Ascend NPU 上使用 torch.compile + Inductor + DVM 进行 FLUX 模型训练时,开发者可能会遇到编译链路和分布式通信方面的基础设施问题。本文基于实际训练场景,系统梳理了从环境搭建、DVM 后端验证到常见报错修复的完整流程,旨在帮助开发者快速定位并解决类似问题。
环境信息:
- torch=2.14.0.dev20260719+cpu
- torch_npu=2.14.0.dev20260719+gitfe48c44
- python=3.12.13
- 基于 torchtitan main 分支修改
一、TorchNPU Master + DVM 环境搭建
1.1 下载 Master 源码
为避免覆盖现有环境,建议单独建立源码目录:
cd /path/to/workspace
git clone -b master --depth 1 https://gitcode.com/Ascend/pytorch.git torch_npu_master
cd torch_npu_master
确认分支与最新提交:
git branch --show-current
git log -1 --oneline
预期输出:master
1.2 确认 DVM 后端存在
编译前务必先检查源码中是否包含 DVM 相关实现:
cd /path/to/torch_npu_master
# 检查 DVM 目录
find torch_npu/_inductor -type d -name '*dvm*'
# 检查 DVM 后端加载逻辑
grep -R "_load_dvm_backend" torch_npu/_inductor
grep -R "NpuDvmKernel" torch_npu/_inductor
grep -R "DvmCodegenInterpreter" torch_npu/_inductor
关键确认点:存在 torch_npu/_inductor/dvm/ 目录,且源码中包含 DVM Backend、DVM Kernel、DVM Codegen 等相关实现。若没有 DVM 路径,则无需继续编译。
1.3 检查 PyTorch 版本兼容性
查看 version.txt 确认 TorchNPU master 支持的 PyTorch 版本:
cat /path/to/torch_npu_master/version.txt
示例输出:
2.15.0
2.14.0
2.13.0
选择兼容版本安装 PyTorch(以 2.13.0 为例):
pip install torch==2.13.0 --index-url https://download.pytorch.org/whl/cpu
python -c "import torch; print(torch.__version__)" # 预期: 2.13.0
1.4 编译与安装 TorchNPU
cd /path/to/torch_npu_master
# 安装编译依赖
pip install -r requirements.txt
pip install pyyaml setuptools auditwheel
# 加载 CANN 环境
source /usr/local/Ascend/cann/set_env.sh
# 编译(指定 Python 版本)
bash ci/build.sh --python=3.12
# 安装编译产物
pip install --force-reinstall --no-deps dist/torch_npu*.whl
使用
--no-deps避免 pip 修改已准备好的 PyTorch 环境。
1.5 验证安装
import os
import torch
import torch_npu
print("torch =", torch.__version__)
print("torch_npu =", torch_npu.__version__)
print("npu path =", torch_npu.__file__)
root = os.path.dirname(torch_npu.__file__)
print("dvm dir exists:", os.path.exists(os.path.join(root, "_inductor", "dvm")))
预期输出:dvm dir exists: True
二、DVM 后端验证与图融合测试
2.1 开启 DVM Backend
运行 Python 程序前设置环境变量:
export TORCHINDUCTOR_NPU_BACKEND=dvm
export TORCH_COMPILE_DEBUG=1
export TORCHINDUCTOR_CACHE_DIR=/tmp/torchinductor_dvm
环境变量说明:
TORCHINDUCTOR_NPU_BACKEND=dvm:指定 NPU Inductor Codegen 使用 DVM BackendTORCH_COMPILE_DEBUG=1:生成调试目录,用于检查 Inductor 最终生成的代码TORCHINDUCTOR_CACHE_DIR:单独指定 DVM 编译缓存,避免复用其他 Backend 的历史缓存
2.2 静态 Shape 最小示例
import torch
import torch_npu
class DvmDemo(torch.nn.Module):
def forward(self, x, y):
value = x * y
value = value + x
return torch.relu(value)
x = torch.randn((128, 128), device="npu", dtype=torch.float32)
y = torch.randn((128, 128), device="npu", dtype=torch.float32)
model = DvmDemo().npu()
compiled_model = torch.compile(model, backend="inductor", dynamic=False)
out = compiled_model(x, y)
torch.npu.synchronize()
print(out.shape, out.device, out.dtype)
编译链路说明:
torch.compile → Dynamo → Inductor → NPU Backend → TORCHINDUCTOR_NPU_BACKEND=dvm → DVM Codegen
2.3 动态 Shape 示例
import torch
import torch_npu
class DynamicDvmDemo(torch.nn.Module):
def forward(self, x, y):
rows = x.shape[0]
return torch.relu(x + y) / rows
def make_inputs(rows):
x = torch.randn((rows, 128), device="npu", dtype=torch.float32)
y = torch.randn((rows, 128), device="npu", dtype=torch.float32)
torch._dynamo.mark_dynamic(x, 0)
torch._dynamo.mark_dynamic(y, 0)
return x, y
model = DynamicDvmDemo().npu()
compiled_model = torch.compile(model, backend="inductor", dynamic=True)
for rows in (32, 48):
x, y = make_inputs(rows)
out = compiled_model(x, y)
expected = model(x, y)
torch.npu.synchronize()
torch.testing.assert_close(out, expected, atol=1e-4, rtol=1e-4)
print(rows, out.shape)
2.4 确认 DVM 代码生成
开启 TORCH_COMPILE_DEBUG=1 后,运行测试程序,然后检查生成的代码:
find torch_compile_debug -name output_code.py -print
grep -R "@dvm.kernel" torch_compile_debug
grep -R "torch_npu._inductor.*dvm" torch_compile_debug
如果 DVM Codegen 生效,output_code.py 中应出现类似结构:
from torch_npu._inductor import dvm
@dvm.kernel(ktype='vector', dyn_shape=False)
def dvm_fused_add_mul_relu_0_build(k):
arg0_1 = k.load([128, 128], dvm.float32)
arg1_1 = k.load([128, 128], dvm.float32)
mul = k.mul(arg0_1, arg1_1)
add = k.add(mul, arg0_1)
relu = k.maximum(add, 0)
k.store(relu, dvm.float32)
dvm_fused_add_mul_relu_0 = dvm_fused_add_mul_relu_0_build
关键判断标准:仅设置环境变量
dvm不能证明 DVM 已参与 Codegen,最终必须以生成代码中出现from torch_npu._inductor import dvm和@dvm.kernel为准。
三、常见报错修复
3.1 报错一:FallbackKernel 没有 data 属性
报错现象
模型 checkpoint 正常加载,进入第一个训练 step 后,torch.compile 在 Inductor 图处理阶段报错:
torch._inductor.exc.InductorError:
AttributeError: 'FallbackKernel' object has no attribute 'data'
调用位置:
torch_npu/_inductor/ascend_npu_ir/ascend_npu_ir/npu/inductor_patch/ir.py
_patch_baseview_realize_hint()
↓
traced_graph = buffer.data.get_traced_graph()
↓
AttributeError: 'FallbackKernel' object has no attribute 'data'
问题本质
TorchNPU 对 Inductor IR 的 Patch 原本只针对以下类型进行了提前返回:
ir.MultiOutput
ir.InputBuffer
ir.ConcatKernel
但计算图中可能出现 ir.FallbackKernel,该对象与普通 Buffer 结构不同,不能访问 .data 属性。
解决方案
修改文件:
/usr/local/python3.12.13/lib/python3.12/site-packages/
torch_npu/_inductor/ascend_npu_ir/ascend_npu_ir/npu/inductor_patch/ir.py
文件中相同判断出现 3 次(约在 230、257、284 行),建议全部修改。
原代码:
if isinstance(buffer, (ir.MultiOutput, ir.InputBuffer, ir.ConcatKernel)):
return r
修改后:
if isinstance(
buffer,
(
ir.MultiOutput,
ir.InputBuffer,
ir.ConcatKernel,
ir.FallbackKernel,
),
):
return r
修改效果
修改后的逻辑为:
realize_hint()
↓
检查 buffer 类型
↓
FallbackKernel?
│
├─ Yes → 直接 return r
│
└─ No → 继续访问 buffer.data.get_traced_graph()
该修改修正的是 TorchNPU Inductor IR 对不同 Buffer 类型的兼容处理,而非 FLUX 模型的计算逻辑。
3.2 报错二:HCCL 通信端口冲突
问题现象
8 卡训练启动时,HCCL 默认使用的 16666 端口被其他任务占用,导致建链失败。
解决方案
显式指定新的 HCCL 端口范围:
export HCCL_NPU_SOCKET_PORT_RANGE="16700-16799"
export HCCL_CONNECT_TIMEOUT=7200
export HCCL_EXEC_TIMEOUT=7200
与 DVM 配置组合
HCCL 配置与 DVM 是相互独立的层次:
- HCCL:多卡通信
- DVM:torch.compile / Inductor 的 NPU Codegen Backend
因此原有 DVM 环境变量继续保留:
export TORCHINDUCTOR_NPU_BACKEND=dvm
export TORCHINDUCTOR_CACHE_DIR=/path/to/cache/torchinductor_dvm
export TORCHINDUCTOR_COMPILE_THREADS=2
export TORCHINDUCTOR_DEBUG=0
四、最终推荐启动配置
4.1 环境变量统一配置
source /usr/local/Ascend/ascend-toolkit/set_env.sh
# 8 卡 NPU
export ASCEND_RT_VISIBLE_DEVICES=0,1,2,3,4,5,6,7
# HCCL:避免默认端口冲突
export HCCL_NPU_SOCKET_PORT_RANGE="16700-16799"
export HCCL_CONNECT_TIMEOUT=7200
export HCCL_EXEC_TIMEOUT=7200
# DVM / Inductor
export TORCHINDUCTOR_NPU_BACKEND=dvm
export TORCHINDUCTOR_CACHE_DIR=/path/to/cache/torchinductor_dvm
export TORCHINDUCTOR_COMPILE_THREADS=2
export TORCHINDUCTOR_DEBUG=0
# 其他
export TOKENIZERS_PARALLELISM=false
export OMP_NUM_THREADS=8
4.2 启动命令
推荐使用一次性环境变量方式,避免污染当前 Shell:
TORCHINDUCTOR_NPU_BACKEND=dvm \
TORCHINDUCTOR_CACHE_DIR=/path/to/cache/torchinductor_dvm \
NGPU=8 \
MODULE=flux \
CONFIG=flux_dev_compile_baseline_8gpu \
./run_train.sh
如需开启 Compile Debug:
TORCHINDUCTOR_NPU_BACKEND=dvm \
TORCH_COMPILE_DEBUG=1 \
TORCHINDUCTOR_CACHE_DIR=/path/to/cache/torchinductor_dvm \
NGPU=8 \
MODULE=flux \
CONFIG=flux_dev_compile_baseline_8gpu \
./run_train.sh
五、问题快速定位表
| 问题 | 所属层 | 根因 | 解决方案 |
|---|---|---|---|
'FallbackKernel' object has no attribute 'data' | TorchNPU / Inductor IR | TorchNPU Patch 将 FallbackKernel 按普通 Buffer 访问 .data | 在 ir.py 3 处类型判断中加入 ir.FallbackKernel |
| HCCL 16666 端口冲突 | NPU 多卡通信 | 默认 HCCL Socket 端口被其他任务占用 | 设置 HCCL_NPU_SOCKET_PORT_RANGE="16700-16799" |
一句话总结
- 报错一:编译器 IR 类型兼容问题,让
FallbackKernel提前返回即可解决。 - 报错二:分布式通信端口问题,为当前任务分配独立的 HCCL 端口范围。
这两个问题均属于运行/编译基础设施层,前者发生在 TorchNPU Inductor Codegen 链路,后者发生在 HCCL 通信链路,并非 FLUX 模型本身的逻辑问题。
六、最终检查清单
正式运行训练前,请依次确认:
- ✅
version.txt与 PyTorch 版本匹配 - ✅ TorchNPU master 源码存在
_inductor/dvm - ✅ 实际 import 的
torch_npu.__file__指向新安装版本 - ✅ 安装目录存在
_inductor/dvm - ✅
TORCHINDUCTOR_NPU_BACKEND=dvm已设置 - ✅ 最小静态 Shape 示例能够运行
- ✅ 动态 Shape 示例能够运行
- ✅
output_code.py中真正出现 DVM import 和@dvm.kernel
第 8 点最为关键:仅设置环境变量为
dvm不能证明 DVM 已参与 Codegen,最终必须以生成代码为准。
鲲鹏昇腾开发者社区是面向全社会开放的“联接全球计算开发者,聚合华为+生态”的社区,内容涵盖鲲鹏、昇腾资源,帮助开发者快速获取所需的知识、经验、软件、工具、算力,支撑开发者易学、好用、成功,成为核心开发者。
更多推荐
所有评论(0)