7
DCU技术达人
PyTorch 训练代码迁到海光 DCU,会被问爆的十个问题
2026-10-15 18:18:07
62
``` # NVIDIA训练代码迁移海光DCU实测问答(8卡K100_AI服务器) 把一套在 NVIDIA 卡上跑熟的训练代码挪到海光 DCU,来问的人最关心的一直是那几件事:要改多少代码、环境怎么配、哪些坑是躲不开的。这份问答来自一台 8 卡 K100_AI 服务器上的实际迁移工作,按被问到的频率排了序。每条答案都是实测结论,不是文档搬运。 ## 问 1:整个迁移里,工作量到底花在哪? 一句话:代码之外。业务代码本身基本不动,真正的时间都花在环境、工具链、依赖版本和结果验证上。如果硬要给个比例,代码层占的工作量不到一成,剩下九成全在"让它在你的机器上正确地跑起来"这件事里。所以别按"改代码"去估工期,按"调环境"去估。 ## 问 2:代码层面具体要改什么? 好消息是 PyTorch 的 DCU 适配把 API 层做得相当彻底。torch.device('cuda')、.cuda()、torch.cuda.is_available()、stream 和 event 那一套,全部原样能用。分布式后端写 nccl 就行——底下实际跑的是 RCCL,但对你的训练脚本来说名字和接口没变,DDP 直接起。真正的改动通常只有两处 shell 层的小事:监控命令从 nvidia-smi 换成 hy-smi;可见性变量从 CUDA_VISIBLE_DEVICES 换成 HIP_VISIBLE_DEVICES。另外两个预期管理:flash-attention 有移植版,装对应包即可;bitsandbytes 这类深度绑定 CUDA 的扩展库没有对等物,训练里用到量化加载的话要换路线(见问 7)。 ## 问 3:环境起步最容易错的一步是什么? 忘记 source DTK 的环境脚本。它不在直觉中的 /etc/profile.d/ 位置,而是在 /opt/dtk-<版本>/env.sh。没吃这个脚本,运行库路径缺失,报错不会在启动瞬间出现,而是延迟到很深的加载阶段才爆出来——你会浪费一轮排查在错误的层面上。把它写进每个启动脚本的第一行,当作肌肉记忆。 ## 问 4:指定了空闲卡,为什么程序还说显存不够? HIP_VISIBLE_DEVICES 的用法和 CUDA 时代一致,但有个反直觉的现象:host 侧看是空卡,device 侧未必。典型场景是上一个进程已经退出,驱动层的显存却还没回收,hy-smi 显示一切正常,新进程启动却报可用显存远小于物理值。处理顺序是:先换一张卡验证判断,确认是残留占用后,用 fuser /dev/kfd 找出所有占卡进程逐个清理,直到 hy-smi 里显存真正归零。 ## 问 5:训练里用到 JIT 编译,有什么要提前知道的? 有,而且集中在 triton 上,实测三个点: 链接器路径变量 TRITON_HIP_LLD_PATH 必须指到 ld.lld 这个完整名字。填成 lld 会持续失败——这个通用驱动按调用它的文件名决定行为,改名调用它就不干活。报错位置在 HSACO 链接阶段,见到 PassManager::run failed 先查这个; 部分 triton 版本(如 3.6 的 HCU 后端)额外要求 clang-18,而主机 DTK 只带 clang-17,需要从镜像内的 aillvm 目录补齐路径(TRITON_HIP_CLANG_PATH)。这是按版本分叉的:3.0/3.1 用默认工具链就够。动手前先 pip show triton 确认版本; 别用版本号新旧推断硬件支持。实测 triton 3.0 认识 gfx928(DCU 架构 target),更新的 3.1 反而报不支持。国产卡生态里,版本号和兼容性不是单调关系,唯一判据是组合实测。 ## 问 6:依赖管理有什么必须立下的规矩? 三条铁律。其一,定制版 vLLM 永远不要 pip 升级——包版本带着厂商适配后缀,装上游版本会丢掉 HIP 适配层,直接不可用,升级只能等厂商发新版。其二,numpy 锁在 2.0 以下:2.x 与现有 torch 版本存在 ABI 不兼容,炸法是静默的,import 或首次算子调用时报出莫名其妙的错。其三,transformers 的大版本升级要单独验证——实测过 5.x 的 tokenizer 新后端不加载某些仓库的自定义子类导致启动崩溃,回退 4.x 解决。整体原则上,一个技术栈一个独立 conda 环境,永远不要"在现有环境里顺手升一下"。 ## 问 7:训练一切正常,输出却是乱的,怎么回事? 这是整个迁移里最凶险的一类问题:不报错、指标正常、token 数正常,唯独内容不对。实测案例是 GPTQ int4 模型——加载成功、服务响应 200,输出却是几百个重复的同一字符。逐项交叉验证后确认是 GPTQ 反量化 kernel 在 HIP 上的数值错误。这类静默损坏没有通用检测手段,只有一条纪律:任何新平台、新量化格式、新 kernel 路径的第一次部署,必须人工读一遍真实输出。准备一个固定的小测试集(几条输入 + 人工确认过的期望输出),每次部署跑一遍,几分钟能兜住这类事故。 ## 问 8:停服务为什么经常停不干净? 三个独立的原因,都可能踩到。显存回收有延迟,进程退了显存未必释放,判断停干净的标准是 hy-smi 归零而非进程消失。按主程序名 pkill -f 会漏掉子进程——推理引擎的 spawn 子进程命令行里不含主程序名,漏杀的子进程继续占卡。还有,新版推理引擎把核心拆成了独立进程,API 端口活着不代表引擎活着,健康检查要打引擎对应的 /health 而不是模型列表接口。 ## 问 9:每次上新环境,有没有一条固定的验证路径? 有,五步链,顺序不能乱: > # 1. import 层:torch 版本与卡数 > python -c "import torch; print(torch.__version__, torch.cuda.device_count())" > # 2. 计算层:一次真实矩阵乘 > python -c "import torch; a=torch.randn(1024,1024,device='cuda'); print((a@a).sum().item())" > # 3. 编译层:跑一个触发 JIT 的小任务(问 5 的三个坑都在这层出现) > # 4. 服务层:最小模型起服务,探 /health > # 5. 正确性层:固定小测试集,人工读输出 第一步永远用最小的模型(0.6B 级别)来探路:加载快、显存小,把"模型放不下""架构不支持"两个变量提前钉死,之后任何失败都可以归因到环境本身。 ## 问 10:如果只记住一件事? 版本号不可信,行为才可信;加载成功不算数,输出正确才算数。把问 9 的五步链存下来,每次过一遍——你踩过的坑就不必再踩第二遍。 ```
K100-ai
全部评论(1)
只看楼主
宇
宇
1楼
:qiang:emoji
10/20
没有更多内容了
--
楼主
Level.2
0 帖子
楼主热帖
暂无数据