昇腾910B实战:hccl-test运行避坑与深度调优指南
最近在几台昇腾910B服务器上折腾分布式训练环境,hccl-test这个看似简单的测试工具,却成了不少团队卡壳的地方。从内核版本不匹配到编译报错,从权限问题到性能调优,每个环节都可能藏着意想不到的坑。这篇文章不是官方文档的复述,而是结合我们团队实际踩坑经验,整理出的实战指南。如果你正在搭建昇腾910B的多卡环境,或者hccl-test运行结果不理想,这里的内容应该能帮你节省不少时间。
目标读者很明确:已经拿到昇腾910B硬件,正在部署多卡通信环境的开发者、系统工程师。我们不会从头讲起如何安装Ubuntu,而是聚焦在那些官方文档可能一笔带过,但实际工作中频繁出问题的环节。特别是当你看到hccl-test编译失败、运行时权限错误、或者带宽远低于预期时,这篇文章提供的排查思路和解决方案,都是经过实际验证的。
1. 环境准备:避开那些“隐藏”的依赖陷阱
很多人以为昇腾环境部署就是按着官方文档一步步走,但真实情况往往复杂得多。特别是当你用的不是“标准”的Ubuntu版本,或者服务器之前装过其他AI加速卡驱动时,问题就会接踵而至。
1.1 内核版本:不只是5.4.0-26-generic那么简单
官方文档通常会指定一个“经过验证”的内核版本,比如Ubuntu 20.04下的5.4.0-26-generic。但如果你用的云服务器或者定制镜像,内核可能已经更新了。这时候盲目降级内核可能引发其他硬件驱动不兼容。
更稳妥的做法是检查内核模块兼容性,而不是死磕特定版本号。首先用uname -r查看当前内核,如果版本高于推荐版本,先别急着降级,试试这个检查:
# 检查当前内核是否包含必要的NPU支持模块 lsmod | grep -i npu # 检查dmesg中是否有NPU相关的错误信息 dmesg | grep -i ascend如果系统里完全没有NPU驱动加载的痕迹,那才需要考虑内核版本问题。实际上,昇腾驱动对较新的内核也有一定支持,但需要确认驱动包是否明确标注了兼容性。
注意:降级内核是最后的手段。先尝试在现有内核上安装驱动,如果安装程序明确报错提示内核不兼容,再考虑更换内核。降级前务必做好系统快照。
1.2 用户与权限:HwHiAiUser的正确配置姿势
创建HwHiAiUser用户组和用户几乎是所有昇腾文档都会提到的步骤,但细节决定成败。这里有几个容易忽略的点:
- 用户ID和组ID的一致性:在多台机器组成的集群中,每台机器上的
HwHiAiUser用户必须拥有相同的UID和GID,否则后续的分布式任务会因权限问题失败。 - 家目录权限:
/home/HwHiAiUser目录的权限设置要合理,既不能太开放(安全风险),也不能太严格(影响软件安装)。
推荐的做法是在所有节点上使用相同的命令创建用户,或者直接同步/etc/passwd和/etc/group文件。创建命令可以稍作调整,明确指定UID和GID:
# 在所有节点上执行相同的命令,确保UID/GID一致 groupadd -g 1001 HwHiAiUser useradd -u 1001 -g HwHiAiUser -d /home/HwHiAiUser -m HwHiAiUser -s /bin/bash1.3 驱动与固件:版本匹配的艺术
昇腾的驱动、固件、CANN工具包之间存在严格的版本依赖关系。从昇腾社区下载时,你会看到类似这样的版本信息:
| 组件 | 版本号示例 | 兼容性要点 |
|---|---|---|
| 驱动 | 23.0.2 | 必须与固件版本匹配,且支持当前内核 |
| 固件 | 7.1.0.4.220 | 硬件微码,版本过旧可能导致功能缺失 |
| CANN工具包 | 8.0.RC3.alpha001 | 必须与驱动版本兼容,新功能依赖新版本 |
实际安装时最容易犯的错误是混合使用不同版本的组件。比如从某个技术博客里复制了驱动安装命令,却从官网下载了最新版的CANN,结果两者不兼容。
我的经验是:始终使用昇腾社区提供的“配套软件”下载页面,那里会列出经过验证的驱动、固件、CANN组合。不要单独搜索某个组件的最新版,兼容性比“新”更重要。
安装驱动时,如果遇到./Ascend-hdk-910-npu-driver_23.0.2_linux-x86-64.run --full --install-for-all执行失败,先别急着找替代方案。检查一下是否缺少基础依赖:
# 安装可能缺少的系统库 sudo apt-get update sudo apt-get install -y kmod linux-headers-$(uname -r) build-essential有时候驱动安装失败只是因为缺少内核头文件,而不是驱动本身有问题。
2. CANN与hccl-test编译:从源码到可执行文件
CANN(Compute Architecture for Neural Networks)是昇腾的软件栈核心,而hccl-test是测试多卡通信性能的关键工具。这一节我们深入编译环节的常见问题。
2.1 CANN安装:不仅仅是运行一个.run文件
下载CANN工具包后,直接运行./Ascend-cann-toolkit_8.0.RC3.alpha001_linux-x86_64.run --install看起来很简单,但安装路径的选择会影响后续所有操作。
安装路径的黄金法则:如果你在多用户环境中部署,或者计划后续升级CANN版本,建议使用自定义路径而非默认路径。例如:
# 指定安装路径,便于版本管理和多版本共存 sudo ./Ascend-cann-toolkit_8.0.RC3.alpha001_linux-x86_64.run --install --install-path=/opt/Ascend/8.0.RC3安装完成后,必须正确设置环境变量。很多人在这一步出错,导致后续hccl-test找不到依赖库。以下是完整的变量设置示例:
# 在~/.bashrc或系统profile中添加 export CANN_HOME=/usr/local/Ascend/ascend-toolkit/latest export ASCEND_HOME_PATH=/usr/local/Ascend export PATH=$CANN_HOME/bin:$PATH export LD_LIBRARY_PATH=$CANN_HOME/lib64:$LD_LIBRARY_PATH export PYTHONPATH=$CANN_HOME/python/site-packages:$PYTHONPATH提示:使用
latest软链接虽然方便,但在生产环境中,建议直接指向具体版本路径,避免意外升级导致的不兼容。
2.2 hccl-test编译:那些容易忽略的细节
官方文档提到hccl-test源码在CANN工具包中,路径是/usr/local/Ascend/ascend-toolkit/latest/tools/hccl_test。但直接进入这个目录执行make可能会失败,原因通常有几个:
问题一:MPI路径不正确
hccl-test依赖OpenMPI,如果MPI安装在不标准的位置,编译时会报错。编译命令中的MPI_HOME必须精确指向OpenMPI的安装目录:
cd /usr/local/Ascend/ascend-toolkit/latest/tools/hccl_test export INSTALL_DIR=/usr/local/Ascend/ascend-toolkit/latest # 确认MPI_HOME路径 which mpicc # 查看mpicc位置,通常为/usr/local/bin/mpicc ls -la /usr/local/bin/mpicc # 查看软链接指向的实际路径 # 假设OpenMPI安装在/usr/local/openmpi-4.1.6 make MPI_HOME=/usr/local/openmpi-4.1.6 ASCEND_DIR=${INSTALL_DIR}问题二:权限不足
即使以root用户编译,也可能因为之前安装的CANN目录权限问题导致失败。检查并修复权限:
# 确保hccl_test目录有写入权限 sudo chown -R $(whoami):$(whoami) /usr/local/Ascend/ascend-toolkit/latest/tools/hccl_test # 如果之前安装CANN时使用了--install-for-all,可能需要调整权限 sudo chmod -R 755 /usr/local/Ascend问题三:依赖库版本冲突
如果你的系统之前安装过其他版本的hccl或通信库,可能会产生冲突。编译前清理环境:
# 检查是否有其他版本的hccl库 ldconfig -p | grep hccl # 临时清空LD_LIBRARY_PATH,只使用CANN自带的库 export LD_LIBRARY_PATH=/usr/local/Ascend/ascend-toolkit/latest/lib64 make clean make MPI_HOME=/usr/local ASCEND_DIR=${INSTALL_DIR}2.3 自定义hccl编译:什么时候需要从源码构建?
大多数情况下,使用CANN自带的hccl库就足够了。但在以下场景,你可能需要从源码编译:
- 需要修改通信算法:默认的all-reduce实现可能不是最优的,针对特定拓扑结构可以优化
- 调试通信问题:需要添加日志或修改超时参数
- 适配非标准硬件拓扑:比如多机多卡的特殊连接方式
从gitee克隆源码编译时,注意版本匹配:
git clone https://gitee.com/ascend/cann-hccl.git cd cann-hccl/ # 切换到与CANN版本匹配的分支 git checkout v0.4-8.0.RC3.alpha003 # nlohmann_json路径需要正确指定,通常在用户include目录或系统目录 ./build.sh --nlohmann_path /usr/include/nlohmann编译成功后,需要将生成的库文件替换或链接到CANN目录中,确保hccl-test使用新编译的版本。
3. 运行hccl-test:从基础测试到深度调优
编译通过只是第一步,运行hccl-test时可能会遇到各种运行时问题。更重要的是,如何解读测试结果并进行调优。
3.1 基础运行命令与常见错误
最基本的8卡测试命令如下:
mpirun --allow-run-as-root -n 8 ./bin/all_reduce_test -b 8K -e 64M -f 2 -d fp32 -o sum -p 8这个命令参数的含义:
-b 8K:测试的最小数据块大小(8KB)-e 64M:测试的最大数据块大小(64MB)-f 2:每次测试的迭代次数-d fp32:数据类型为单精度浮点数-o sum:操作为求和-p 8:进程数(卡数)
常见错误一:权限问题
即使加了--allow-run-as-root,有时还是会遇到权限错误。这是因为昇腾设备文件(/dev/davinci*)的权限设置。检查并修复:
# 检查设备文件权限 ls -la /dev/davinci* # 确保HwHiAiUser用户可以访问 sudo chown -R root:HwHiAiUser /dev/davinci* sudo chmod 660 /dev/davinci*常见错误二:MPI进程启动失败
错误信息可能类似ORTE was unable to reliably start one or more daemons。这通常是因为OpenMPI的环境变量设置问题。尝试:
# 设置OpenMPI不依赖ssh export OMPI_MCA_plm_rsh_agent=/bin/false # 或者使用--host参数明确指定 mpirun --allow-run-as-root --host localhost:8 -n 8 ./bin/all_reduce_test ...常见错误三:hccl库加载失败
如果看到libhccl.so not found之类的错误,需要确保库路径正确:
# 将hccl库路径加入LD_LIBRARY_PATH export LD_LIBRARY_PATH=/usr/local/Ascend/ascend-toolkit/latest/lib64:$LD_LIBRARY_PATH # 或者使用ldconfig sudo ldconfig /usr/local/Ascend/ascend-toolkit/latest/lib643.2 测试结果解读:什么才是“好”的带宽?
运行成功后,你会看到类似这样的输出:
data_size(Bytes): | aveg_time(us): | alg_bandwidth(GB/s): | check_result: 8192 | 649.85 | 0.01261 | success 16384 | 515.75 | 0.03177 | success 32768 | 509.05 | 0.06437 | success 65536 | 505.00 | 0.12977 | success 131072 | 505.10 | 0.25950 | success 262144 | 501.70 | 0.52251 | success 524288 | 789.70 | 0.66391 | success 1048576 | 1454.90 | 0.72072 | success 2097152 | 3141.60 | 0.66754 | success 4194304 | 6769.45 | 0.61959 | success 8388608 | 13935.30 | 0.60197 | success 16777216 | 27919.90 | 0.60091 | success 33554432 | 55862.55 | 0.60066 | success 67108864 | 111805.80 | 0.60023 | success如何解读这些数据?有几个关键点:
- 小数据块性能:8KB到256KB的数据块,带宽通常较低,这是通信延迟主导的阶段
- 峰值带宽:在1MB到4MB之间,带宽达到峰值(本例约0.72GB/s)
- 大数据块稳定性:超过8MB后,带宽趋于稳定,反映的是可持续通信带宽
与理论值对比:昇腾910B的卡间互联(HCCS)理论带宽是多少?根据官方资料,单方向理论峰值约30GB/s,但实际应用层能到0.7-1.2GB/s是正常范围。如果远低于这个值(比如只有0.1GB/s),就需要排查问题了。
3.3 性能调优:让带宽更接近理论值
如果测试带宽不理想,可以尝试以下调优手段:
调整MPI参数:
# 尝试不同的MPI通信算法 mpirun --allow-run-as-root -n 8 --mca btl vader,self ./bin/all_reduce_test ... # 调整通信缓冲区大小 export OMPI_MCA_btl_vader_single_copy_mechanism=none调整hccl参数:
HCCL有一些环境变量可以调优通信性能:
# 启用大页内存,减少TLB miss export HCCL_USE_HUGEPAGE=1 # 调整通信线程数 export HCCL_COMM_THREAD_NUM=4 # 设置流控参数,避免缓冲区溢出 export HCCL_FLOW_CONTROL=1 export HCCL_FLOW_CONTROL_WINDOW_SIZE=16系统级调优:
- CPU频率:确保CPU运行在性能模式,而非节能模式
- NUMA绑定:将进程绑定到靠近对应PCIe插槽的CPU核
- 中断亲和性:设置NPU中断处理在特定CPU核,减少上下文切换
# 检查CPU频率 cpupower frequency-info # 设置为性能模式 sudo cpupower frequency-set -g performance # NUMA绑定示例(假设卡0-3在NUMA node0,卡4-7在NUMA node1) mpirun --allow-run-as-root -n 8 --bind-to numa --map-by ppr:4:node ./bin/all_reduce_test ...4. 高级问题排查:当基础方法都不奏效时
有些问题不会在第一次运行时出现,而是在特定条件下才暴露。这一节我们探讨那些“诡异”的问题和解决方案。
4.1 间歇性通信失败:如何定位偶发问题?
最让人头疼的是那种时好时坏的问题。hccl-test可能今天跑得好好的,明天就失败,或者连续成功几次后突然失败。
诊断步骤:
- 检查系统日志:
dmesg -T | grep -i ascend查看内核日志中是否有NPU相关错误 - 监控系统资源:在测试运行时,同时监控系统状态
# 在一个终端运行测试 mpirun --allow-run-as-root -n 8 ./bin/all_reduce_test ... # 在另一个终端监控 watch -n 1 "nvidia-smi topo -m" # 查看拓扑(如果有NVIDIA卡) watch -n 1 "cat /proc/interrupts | grep davinci" # 查看中断计数- 压力测试:运行长时间、高强度的测试,看是否会在特定时间点失败
# 循环运行100次测试 for i in {1..100}; do echo "Run $i" timeout 30 mpirun --allow-run-as-root -n 8 ./bin/all_reduce_test -b 1M -e 64M -f 100 -d fp32 if [ $? -ne 0 ]; then echo "Failed at run $i" break fi done常见原因与解决方案:
- 内存泄漏:长时间运行后内存耗尽。检查是否有进程未正确释放资源
- 中断风暴:某个设备中断异常,导致系统响应变慢。尝试调整中断亲和性
- 温度过高:NPU温度过高触发降频或保护。检查散热和风扇状态
4.2 多机测试:跨节点通信的特殊考量
虽然hccl-test主要用于单机多卡测试,但原理同样适用于多机环境。多机测试时需要注意:
网络配置:
- 确保节点间网络互通,防火墙开放必要端口
- 使用高速网络(InfiniBand或高速以太网)
- 设置正确的hostfile
# hostfile示例(hosts.txt) node1 slots=8 node2 slots=8 # 多机运行命令 mpirun --allow-run-as-root -hostfile hosts.txt -n 16 ./bin/all_reduce_test ...SSH无密码登录: OpenMPI默认使用ssh在节点间启动进程,需要配置无密码登录:
# 生成密钥(如果还没有) ssh-keygen -t rsa # 复制公钥到所有节点(包括自己) ssh-copy-id node1 ssh-copy-id node2多机性能分析: 多机环境下,除了卡间通信,还要考虑节点间网络带宽。可以使用ibstat(InfiniBand)或ethtool(以太网)检查网络状态。
4.3 与深度学习框架的集成测试
hccl-test通过后,真正的考验是与PyTorch、TensorFlow等框架的集成。这里有一些额外的检查点:
PyTorch + Ascend适配:
- 确保安装了正确版本的torch_npu
- 检查设备是否被正确识别:
import torch import torch_npu print(f"NPU available: {torch_npu.npu.is_available()}") print(f"NPU count: {torch_npu.npu.device_count()}") # 测试简单的张量操作 x = torch.randn(1000, 1000).npu() y = torch.randn(1000, 1000).npu() z = x @ y # 矩阵乘法 print(z.mean())- 测试分布式训练:
import torch.distributed as dist import torch_npu # 初始化进程组 dist.init_process_group(backend='hccl', init_method='env://') # 创建模型并移动到NPU model = YourModel().npu() # 使用DistributedDataParallel model = torch.nn.parallel.DistributedDataParallel(model)常见集成问题:
- 版本不匹配:PyTorch、torch_npu、CANN版本必须严格匹配
- 内存不足:多卡训练时每卡内存可能不足,需要调整batch size
- 通信死锁:某些操作顺序可能导致死锁,需要仔细设计数据流
4.4 性能瓶颈分析工具
当hccl-test带宽不理想时,可以使用一些工具进行深度分析:
Ascend性能分析工具:
# 安装性能分析工具 # 通常包含在CANN工具包中 # 运行性能分析 msprof --application="mpirun -n 8 ./bin/all_reduce_test" --output=./profiling系统级监控:
# 实时监控NPU使用情况 npu-smi info # 监控PCIe带宽 sudo apt-get install pciutils watch -n 1 "lspci -vvv | grep -A 10 'Processing accelerators'" # 监控内存带宽 sudo apt-get install likwid likwid-perfctr -C 0-7 -g MEM -m ./bin/all_reduce_test自定义性能测试:
除了标准的all_reduce_test,还可以编写自定义测试来定位特定问题:
// 简化的点对点带宽测试 #include <hccl/hccl.h> #include <iostream> int main() { // 初始化HCCL HcclRootInfo root_info; // ... 初始化代码 // 测试不同消息大小的点对点带宽 for (size_t size = 1024; size <= 1024*1024*64; size *= 2) { // 分配内存,执行通信,测量时间 // ... 测试代码 } return 0; }在实际项目中,我们遇到过hccl-test带宽正常,但实际训练时通信效率低下的情况。最后发现是框架层的数据准备和通信重叠不够充分。这时候就需要结合应用特点,调整通信策略和数据流。
比如在BERT训练中,我们通过调整梯度累积步数,让通信时间更好地与计算时间重叠,最终将整体训练速度提升了15%。这种优化需要深入理解模型的计算通信比,不是单纯看hccl-test带宽就能解决的。
说到底,hccl-test只是一个基准测试工具,它帮你验证硬件和基础软件栈是否正常。真正的性能优化,需要结合具体应用场景,从系统配置、算法实现、框架调优多个层面综合考虑。每个昇腾910B的部署环境都有其独特性,遇到的问题也不尽相同,但掌握这些排查思路和工具,至少能让你在遇到问题时,知道该从哪里入手。