Ascend.cl
华为集合通信性能测试
Install / Use
/learn @zzudongxiang/Ascend.clREADME
1. 快速使用
HCCL(Huawei Collective Communication Library)是基于昇腾AI处理器的高性能集合通信库,其主要功能与作用与Nvidia的NCCL库相似,主要用于集合通信,CANN库种自带一套测试工具用以分析集合通信性能。
1.1 编译环境配置
前置环境配置阶段请参考Ascend上创建Docker,后续的所有流程均需要在具备HCCL硬件的平台上实现,需要注意的是,建议使用的Ubuntu版本大于等于20.04LTS,否则可能会遇到VSCode不支持的情况。
1.1.1 CANN
CANN的配置过程参考Ascend上创建Docker文档的安装CANN章节,并记录安装位置,以备后续使用
完成CANN后,建议在~/.bashrc文件中添加对应的环境变量,例如:
# 使用nano打开~/.bashrc文件
nano ~/.bashrc
在文件的最后添加export ASCEND_HOME=/usr/local/Ascend/ascend-toolkit/latest
1.1.2 OpenMPI
在OpenMPI官网找到对应版本的安装包下载,然后解压缩安装包,以mpich-4.2.0版本为例:
# mpich下载链接参考:https://www.mpich.org/static/downloads
wget https://www.mpich.org/static/downloads/4.2.0/mpich-4.2.0.tar.gz
# 解压缩mpich压缩包
tar -zxvf mpich-4.2.0.tar.gz
配置mpi的安装路径,以/root/mpich路径为例:
# 新建文件夹
mkdir ~/mpich
# 进入解压缩后的mpich文件夹
cd mpich-4.2.0
# 配置安装路径
./configure -prefix=/root/mpich --disable-fortran
使用make命令构建mpich的可执行文件,该过程可能耗时比较长
make
make install
完后后将mpich添加到环境变量种,并添加对应的链接库和帮助文件
# 修改~/.bashrc文件
nano ~/.bashrc
在最后一行添加以下内容:
export MPI_HOME=/root/mpichexport PATH=$MPI_HOME/bin:$PATHexport MANPATH=$MPI_HOME/man:$MANPATHexport LD_LIBRARY_PATH=$MPI_HOME/lib:$LD_LIBRARY_PATH
1.2 文件编译
本章节参考链接:【昇腾】Ascend Snt9B集合通信算子单机多卡性能测试指导
为了方便后续修改hccl_test内的文件,且保持一份未修改的源文件,建议将对应的文件复制到用户路径下,例如复制到/root/Workdir路径下
cp -r /usr/local/Ascend/ascend-toolkit/7.0.0/tools/hccl_test /root/Workdir/
由于配置的ASCEND_HOME指向的文件夹是一个链接,在复制hccl_test文件夹的时候需要复制源文件而不是文件夹链接,因此可以通过命令查看其对应的真实文件路径
# 切换到ASCEND_HOME路径
cd $ASCEND_HOME/tools
# 查看链接的真实地址
ll

切换到复制后的文件夹后,执行编译命令:
# 切换到复制后的文件夹中
cd /root/Workdir/hccl_test
# 编译文件
make MPI_HOME=/home/mpich ASCEND_DIR=/usr/local/Ascend/ascend-toolkit/latest
编译完成后会在新建的./bin文件夹中出现多个*_test可执行文件
1.3 运行测试案例
执行以下命令即可进行简单测试:
# mpirun -n 8 * 表示使用mpi拉起8个进程,建议与最后的-p参数保持一致
mpirun -n 8 ./bin/all_reduce_test -b 8 -e 2048M -f 2 -p 8
对应的测试配置参数及其释义如下:
-b,--minbytes <min size in bytes>
-e,--maxbytes <max size in bytes>
-i,--stepbytes <increment size>
-f,--stepfactor <increment factor>
-n,--iters <iteration count>
-o,--op <sum/prod/min/max>
-d,--datatype <int8/int16/int32/fp16/fp32/int64/uint64/uint8/uint16/uint32/fp64/bfp16>
-r,--root <root>
-w,--warmup_iters <warmup iteration count>
-c,--check <result verification> 0:disabled 1:enabled.
-p,--npus <npus used for one node>
-h,--help
如果需要修改HCCL通信的缓冲区大小(每次HCCL通信可发送/接收的数据包大小),可以在执行之前设置环境变量HCCL_BUFFSIZE,单位MB,例如设置缓冲区大小为2GB:
export HCCL_BUFFSIZE=2048
2. 调试环境配置
为了方便调试和分析hccl_test编写的测试工具在运行中各个参数与之对应的实际生效作用关系,需要配置调试环境进行单步调试,通过抓取运行中的寄存器值可以看到每个参数实际对应的功能。
2.1 VSCode设置
VSCode需要安装Remote-SSH插件连接到远程服务器,插件安装过程参考其他教程,在使用Remote-SSH插件连接到远程服务器后需要在远程服务器上安装C/C++、Jupyter、Python等扩展
使用Remote-SSH登录到服务器上的指定文件夹,并新建.vscode文件夹,并在该文件夹下新建以下三个配置文件c_cpp_properties.json、launch.json、tasks.json
2.1.1 c_cpp_properties.json
c_cpp_properties.json 文件主要用于配置在编辑器中是否显示静态检查结果,例如部分头文件无法找到会出现红色波浪等
- includePath:将代码所需的头文件路径添加到该字段下即可
2.1.2 launch.json
launch.json 文件主要用于配置调试器,在调试C/C++工具时需要先安装gdb工具,安装命令:apt install gdb
- program:编译后生成的可执行文件,编译参数见
tasks.json文件 - envFile:程序运行时添加的环境变量,可参考
.env文件 - preLaunchTask:编译可执行文件的参数配置,参考
tasks.json文件
2.1.3 tasks.json
tasks.json 文件主要用于编译生成可执行文件,相关的编译参数需要添加到该文件中,参数信息参考Makefile文件
-
label:与
launch.json文件中的preLaunchTask字段对应 -
args:编译参数,具体参考
Makefile文件
2.2 MPI并行调试
1. 运行启动命令
在VSCode中的Debug菜单栏选择hccl_debug对待调试的文件进行编译,或者切换到./hccl/文件夹下使用make命令编译所有可执行文件,然后在新的Terminal切换到当前文件目录执行以下命令,以hccl_p2p_rootinfo_test为例,创建两个进程。
# 先设置环境变量,使当前控制台的进行等待调试进程attach到进程中
export HCCL_MPI_DEBUG=1
# 启动2个进程,对2个进程进行Attach调试
mpirun -n 2 ./bin/hccl_p2p_rootinfo_test
此时界面Terminal的界面将会卡住,等待用户的调试进程Attach
2. 调试代码
在main.cc的第一行打断点,并选择hccl_mpi_debug开始进程Attach,待Attach成功后,修改hccl_mpi_debug的值为false然后就可以跳出while循环,进行代码调试了。
注意Attach的时候选择的进程为运行的进程,而非mpi进程,本例中可以搜索并选择hccl_p2p_rootinfo_test进程进行Attach
2.3 msprof设置
本章节参考:采集昇腾AI处理器系统数据,可以根据文档内容直接运行对应的执行参数,但是为了方便程序运行与调试,请参考8卡Trace采集脚本
运行脚本后会在./log/prof/*.json路径中出现对应的timeline文件,打开Perfetto网站,导入对应的json文件即可查看和分析对应的测试Trace

点对点NPU测试(数据交换)测试速度比msprof抓取Trace快,可以测试不同数据包下的性能表现,测试脚本参考点对点测试脚本
| aveg_time | alg_bandwidt |
| :----------------------------------------------------------: | :----------------------------------------------------------: |
|
|
|
3. 点对点通信
点对点通信代码参考hccl_p2p_rootinfo_test.cc文件,使用HCCL的API进行数据收发,代码架与原生hccl_test相同,在进行点对点通信时,rank_id % 2 == 0的rank为发送者,否则为接收者,因此在进行点对点通信时需要确保参与通信的NPU卡个数为偶数,否则可能会导致通信阻塞。
3.1 点对点通信带宽
以NPU0与NPU1为例点对点测试,每次申请的内存大小为1kB至2GB(实际通信量为该值的一半),每次翻一倍,HCCL的通信Buffer设置为2GB(确保不需要切换缓冲区),多次测试的带宽数据如下图所示:

通信带宽最终稳定在20GB/s左右,与Trace分析结果一致。
3.2 Trace分析
以NPU0与NPU1为例点对点测试,申请的内存大小为2GB,实际通信大小为1GB,HCCL的通信Buffer设置为2GB(确保不需要切换缓冲区):
所有的Trace文件参考:p2p_trace.zip

Stage 10 - Rank_0在本地复制1GB数据到HCCL缓冲区
Stage 00&Stage11 - 等待传输1GB数据
Stage 01 - Rank_1从本地HCCL缓冲区复制1GB数据到接收区
3.3 问题
在代码里面NPU0作为发送者发送数据给NPU1,但是在Trace中显示的却是NPU0在等待,NPU1执行了memcpy操作,且memcpy的src为1,dst为0,且从结果来看代码操作逻辑是正常的。
内存检查
rank_0把发送区所有数据置为1,rank_1把所有发送去数据置为2,经过p2p通信(rank_0发送数据给rank_1)后,rank_1的接收区数据变为了1,说明接收了来自rank_0的数据,内存检查结果正常。
4. 集合通信测试结果
4.1 Trace Timeline分析
本章节后续的分析基于Broadcast测试案例,数据包大小设置为2GB,数据类型为float(4字节),HCCL通信Buffer大小为2G,4张NPU卡作为测试条件
Trace源文件参考:broadcast_2.0GB.zip

Stage 1 - 1.692ms
由于设置的数据包大小为2GB,则需要申请2GB空间的集合通信内存(Device侧内存),不同的算法根据其算法的特点,申请的内存大小有所不同
备注:数据类型是float,因此实际申请的是0.5GB个float数据所占用的空间,后续均以字节数表示
main()
|- hccl_test->opbase_test_by_data_size()
|- $ hccl_test->hccl_op_base_test()
|- $ aclrtMalloc()
Stage 2 - 8.097s
申请同样大小(2GB)的Host侧内存(64.476ms)并进行初始化(8.033s)
main()
|- hccl_test->opbase_test_by_data_size()
|- hccl_test->hccl_op_base_test()
|- $ aclrtMallocHost()
|- $ hccl_host_buf_init()
Stage 3 - 85.87ms
Host侧的内存进行memcpy操作到Device侧
main()
|- hccl_test->opbase_test_by_data_size()
|- hccl_test->hccl_op_base_test()
|- $ aclrtMemcpy()
Stage 4 - 4.286s
Host侧申请2G的校验内存空间(65.484ms),用于校验内存数据,并初始化校验内存空间(4.221s)
main()
|- hccl_test->opbase_test_by_data_size()
|- hccl_test->hccl_op_base_test()
|- $ init_buf_val()
|- $ aclrtMallocHost()
|- $ hccl_host_buf_init()
Stage 5 - 1750.615ms
开始集合通信,相关的细节在下一个章节进行分析
main()
|- hccl_test->opbase_test_by_data_size()
|- hccl_test->hccl_op_base_test()
|- $ HcclBroadcast()
Stage 6 - 170.652ms
申请Host侧的2GB校验空间(64.736ms),并将其Device侧的通信结果复制到该空间中(105.916ms)
main()
|- hccl_test->opbase_test_by_data_size()
|- hccl_test->hccl_op_base_test()
|- $ check_buf_result()
|- $ aclrtMallocHost()
|- $ aclrtMemcpy()
Stage 7 - 3.535s
验证HCCL的通信结果,计算并打印HCCL的测试结果
main()
|- hccl_test->opbase_test_by_data_size()
|- hccl_test->hccl_op_base_test()
|- check_buf_result()
|- $ check_buf_result_float()
|- $ cal_execution_time()
Stage 8 - 115.893ms
释放Device侧的2GB大小的Buffer
main()
|- hccl_test->opbase_test_by_data_size()
|- hccl_test->hccl_op_base_test()
|- $ aclrtFree()
Stage 9 - 19.554s
释放用于校验的Buffer,一共三块,每块大小2GB
- host_buf 是Stage 2申请的Host侧内存,用于初始化Device侧内存数据
- check_buf 是Stage 4申请的Host侧内存,储存用于校验的原始数据
- recv_buff_temp 是Stage 7申请的Host侧内存,储存来自Device侧的数据
main()
|- hccl_test->opbase_test_by_data_size()
|- hccl_test->hccl_op_base_test()
|- $ destory_check_buf()
|- $ aclrtFreeHost()
Timeline

4.2 不同集合通信Buffer
上述的测试均基于BufferSize足够大的情况下(所有数据包均可一次发送或接收完成),当HCCL的Buffer不够大时,传输2048MB的数据进行切片分割
以Broadcast算法为例,分别设置HCCL Buffer大小为2048MB和10MB进行测试,HCCL通信一次对应的Trace结果如下图所示
源文件参考路径:broadcast_buffer2048M.zip和broadcast_buffer10M.zip
4.2.1 2048MB

4.2.2 10MB

4.3 不同集合通信算法
在Trace中,通信带宽数据有两处可以查阅到,一是查看HBM数据,该数据按照一定的时间间隔进行采集,整体的颗粒度不够高,但是可以从全局查看整体变化趋势;二是在HCCL的memcpy阶段存在size字段,可以查看到每个阶段具体的memcpy内存数量
在HCCL的memcpy字段下不仅存在size字段,还存在link type、bandwidth、transport type、src rank、dst rank等字段,可以用于后续分析
以数据包大小设置为2GB,数据类型为float(4字节),HCCL通信Buffer大小为2G,8张NPU卡作为测试条件,相关的原始文件参考trace_log/
需要注意的是本文拿到的所有地址均为虚拟地址,每个rank拿到的虚拟地址可能是相同的(由内存管理模块分配)但对应的物理地址是不同的,因此地址信息不能作为是否Buffer复用的判定依据

4.3.1 all_gather
A. 通信原语
AllGather属于多对多的通信原语,具有多个数据发送者,多个数据接收者,可
Related Skills
node-connect
335.9kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
82.7kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
335.9kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
commit-push-pr
82.7kCommit, push, and open a PR
