CANN HCCL 通信算子 C 接口完全指南:集合通信与点对点通信 API 详解
【免费下载链接】hccl集合通信库(Huawei Collective Communication Library,简称HCCL)是基于昇腾AI处理器的高性能集合通信库,为计算集群提供高性能、高可靠的通信方案项目地址: https://gitcode.com/cann/hccl
HCCL(Huawei Collective Communication Library,华为集合通信库)是基于昇腾 AI 处理器的高性能集合通信库,为计算集群提供高性能、高可靠的通信方案。本文以 docs/zh/api_ref 下 HCCL API 参考文档为主体,系统梳理 HCCL 对外 C 接口的完整知识体系:先讲清接口分类与头文件/库文件的依赖关系,再逐一详解 11 个集合通信算子与 3 个点对点通信算子的函数原型、参数语义、数据类型支持、返回值与使用约束,并给出可直接套用的调用示例。读完本文,你将能准确掌握每个 HCCL 算子的适用场景与调用方法,理解通信域(comm)、任务流(stream)与数据类型(HcclDataType)的配套使用规则,并避开对称内存污染、缓存区容量、串行下发等常见陷阱。
一、接口全景:三类对外接口与头文件/库文件
HCCL 对外接口按功能分为以下三类,全部以 C 语言接口形式对外提供:
| 接口类别 | 包含接口 | 说明 |
|---|---|---|
| 集合通信算子 | AllReduce、Broadcast、AllGather、AllGatherV、ReduceScatter、ReduceScatterV、Scatter、Reduce、AlltoAll、AlltoAllV、AlltoAllVC | 共 11 个集合通信接口,支持多节点间的数据广播、归约、收集和分发操作。 |
| 点对点通信算子 | Send、Recv、BatchSendRecv | 共 3 个点对点通信接口,支持单 rank 到单 rank 的单收单发,以及多个 rank 之间的批量收发。 |
| MC2 自定义算子 | HcclKfc*参数对象接口与HcclCreateOpResCtx | MC2(Kernel Fusion Custom)自定义算子框架接口,用于构造通信资源上下文。 |
1.1 头文件与库文件依赖关系
安装固件、驱动及 CANN 软件包后,编译、运行应用程序时才能引用到 HCCL 接口的头文件与库文件。HCCL 接口的头文件位于${INSTALL_DIR}/include/hccl/目录下,库文件位于${INSTALL_DIR}/lib64/目录下,其中${INSTALL_DIR}为 CANN 软件安装后的文件存储路径(以 root 用户安装为例,默认路径为/usr/local/Ascend/cann)。
| 定义接口的头文件 | 用途 | 对应的库文件 |
|---|---|---|
hccl/hccl.h | 定义集合通信与点对点通信算子接口。 | libhccl.so |
hccl/hccl_mc2.h | 定义 MC2 自定义算子框架接口,包括HcclKfc*参数对象分配/设置与HcclCreateOpResCtx通信资源上下文创建等接口。 | libhccl.so |
[!CAUTION] 注意 编译 HCCL 接口程序时,请按照 include 的头文件依赖对应的库文件,如果引用多余的 so 文件,可能导致版本功能异常或后续版本升级时存在兼容性问题。
从当前仓库源码可以进一步印证头文件的依赖关系:include/hccl.h 在声明算子接口前,通过#include <hccl/hccl_types.h>、#include <hccl/hccl_comm.h>、#include <acl/acl.h>引入公共数据类型(HcclResult、HcclDataType、HcclReduceOp、HcclComm、HcclSendRecvItem等)、通信域类型以及 ACL 运行管理类型(aclrtStream);include/hccl_mc2.h 则基于hccl/hccl_types.h与hccl/hccl_res.h提供 MC2 框架接口。仓库中 docs/zh/api_ref/comm_op_interface/data_type_def.md 汇总了这些公共数据类型(HcclResult、HcclReduceOp、HcclComm、HcclDataType、HcclSendRecvType、HcclSendRecvItem)的索引。
HCCL 以cann-hccl_<version>_linux-<arch>.run安装包形式发布,包含libhccl.so、对外头文件与aicpu_hccl.tar.gz(HCCL AI CPU 算子包);静态构建模式另产出libhccl_static.a。源码编译与安装流程详见构建指南,各算子的原型定义、参数说明与数据类型支持详见通信算子接口。
1.2 公共调用骨架
所有通信算子接口都遵循同一个调用骨架:申请 Device 内存 → 初始化通信域 → 创建任务流 → 下发算子 → 同步等待 → 释放资源。以 examples/01_point_to_point/01_send_recv/main.cc 中体现的流程为例:
aclrtSetDevice(device); // 设置当前线程操作的设备 HcclComm hcclComm; HcclCommInitRootInfo(devCount, &rootInfo, device, &hcclComm); // 初始化集合通信域 aclrtStream stream; aclrtCreateStream(&stream); // 创建任务流 // ... 申请并初始化 Device 侧 sendBuf / recvBuf ... HcclXxx(..., hcclComm, stream); // 下发通信算子 aclrtSynchronizeStream(stream); // 阻塞等待任务执行完成 aclrtFree(sendBuf); aclrtFree(recvBuf); // 释放 Device 内存 aclrtDestroyStream(stream); // 销毁任务流 HcclCommDestroy(hcclComm); // 销毁通信域其中HcclCommInitRootInfo基于 root 节点的HcclRootInfo(rank 表信息)初始化通信域;comm标识集合通信操作所在的通信域,stream表示本 rank 所使用的 ACL 任务流。仓库 examples/02_collectives 下还提供了 allreduce、broadcast、allgather、reduce_scatter、reduce、alltoall、alltoallv、alltoallvc、scatter 等全套集合通信示例。
二、公共类型与返回值约定
所有算子接口统一返回HcclResult,其取值与含义如下:
| 返回值 | 说明 |
|---|---|
| HCCL_SUCCESS | 接口调用成功。 |
| HCCL_E_PTR | 传入的指针参数为空(如 comm、buf、stream 等为 nullptr,各算子的具体判空项略有差异)。 |
| HCCL_E_PARA | 传入的参数无效(如 count 超过上限、root 越界等)。 |
| HCCL_E_NOT_SUPPORT | 操作不被支持(如 dataType 非法或当前型号不支持、混合组网不支持等)。 |
| HCCL_E_INTERNAL | 内部错误。 |
所有算子还共享以下通用约束:
- 多个通信域下的所有通信算子在每个 Device 上需要保证串行下发,不允许乱序、多线程并发下发,也不支持线程重入。
- 在同一 Device 上,同一通信域内的所有通信算子的下发线程需要使用相同的 Context。
三、集合通信算子详解(11 个)
HCCL 集合通信接口提供 Broadcast、AllGather、AllReduce、Reduce、ReduceScatter、AlltoAll 等原语,支持多节点间的数据广播、归约、收集和分发操作,详见集合通信文档。
3.1 HcclBroadcast:数据广播
将通信域内 root 节点的数据广播到其他 rank,原型为:
HcclResult HcclBroadcast(void *buf, uint64_t count, HcclDataType dataType, uint32_t root, HcclComm comm, aclrtStream stream)| 参数 | 输入/输出 | 描述 |
|---|---|---|
| buf | 输入/输出 | 数据 buffer 地址。root 节点为源数据 buffer;非 root 节点为数据接收 buffer。 |
| count | 输入 | 参与 broadcast 操作的数据个数(如仅 1 个 int32 数据参与,则 count=1)。 |
| dataType | 输入 | 操作的数据类型(HcclDataType)。 |
| root | 输入 | 作为 broadcast root 的 rank id。 |
| comm / stream | 输入 | 通信域 / 本 rank 所使用的 stream。 |
关键约束:所有 rank 的 count、dataType、root 均应相同;全局只能有 1 个 root 节点。调用示例:
void *buf = nullptr; // root 为数据源,非 root 为接收 buffer uint64_t count = 8; size_t mallocSize = count * sizeof(float); aclrtMalloc(&buf, mallocSize, ACL_MEM_MALLOC_HUGE_ONLY); if (deviceId == rootRank) { // root 节点构造输入数据 aclrtMemcpy(buf, mallocSize, hostBuf, mallocSize, ACL_MEMCPY_HOST_TO_DEVICE); } HcclCommInitRootInfo(rankSize, &rootInfo, deviceId, &hcclComm); aclrtCreateStream(&stream); HcclBroadcast(buf, count, HCCL_DATA_TYPE_FP32, rootRank, hcclComm, stream); aclrtSynchronizeStream(stream); // 阻塞等待集合通信任务执行完成 aclrtFree(buf); aclrtDestroyStream(stream); HcclCommDestroy(hcclComm);3.2 HcclAllGather / HcclAllGatherV:全收集
HcclAllGather将通信域内所有节点的输入按照 rank id 重新排序后拼接,再将结果发送到所有节点的输出,即每个节点的 AllGather 输出都是一样的:
HcclResult HcclAllGather(void *sendBuf, void *recvBuf, uint64_t sendCount, HcclDataType dataType, HcclComm comm, aclrtStream stream)recvBuf 的数据 size 等于sendCount * rank size;所有 rank 的 sendCount、dataType 均应相同。典型调用:
uint32_t rankSize = 8; uint64_t sendCount = 1; size_t sendSize = sendCount * sizeof(float); size_t recvSize = rankSize * sendCount * sizeof(float); aclrtMalloc(&sendBuf, sendSize, ACL_MEM_MALLOC_HUGE_ONLY); aclrtMalloc(&recvBuf, recvSize, ACL_MEM_MALLOC_HUGE_ONLY); HcclCommInitRootInfo(rankSize, &rootInfo, devId, &hcclComm); aclrtCreateStream(&stream); // 将通信域内所有 rank 的 sendBuf 按 rank_id 顺序拼接后发送到所有 rank 的 recvBuf HcclAllGather(sendBuf, recvBuf, sendCount, HCCL_DATA_TYPE_FP32, hcclComm, stream); aclrtSynchronizeStream(stream);HcclAllGatherV与 AllGather 语义相同,但支持通信域内不同节点输入不同大小的数据量,通过recvCounts(第 i 个元素表示需要从 rank i 接收的数据量,须与 rank i 的 sendCount 相同)与recvDispls(第 i 个元素表示从 rank i 接收的数据在 recvBuf 中的起始偏移量,单位为 dataType)两个 uint64 数组描述每个 rank 的接收布局:
HcclResult HcclAllGatherV(void *sendBuf, uint64_t sendCount, void *recvBuf, const void *recvCounts, const void *recvDispls, HcclDataType dataType, HcclComm comm, aclrtStream stream)注意 recvBuf 与 sendBuf 配置的地址不能相同。约束上,所有 rank 的 recvCounts、recvDispls、dataType 均应相同;Atlas A3 系列与 Atlas 300I Duo 推理卡仅支持单 Server 场景(后者单 Server 最大 2 张卡即 4 个 NPU);Atlas A2 系列仅支持多机对称分布场景。
3.3 HcclReduce / HcclAllReduce:归约
HcclReduce将所有 rank 的数据执行归约操作(由 op 参数指定)后,把结果发送到root 节点的指定位置:
HcclResult HcclReduce(void *sendBuf, void *recvBuf, uint64_t count, HcclDataType dataType, HcclReduceOp op, uint32_t root, HcclComm comm, aclrtStream stream)HcclAllReduce则将归约结果发送到所有节点的输出 buffer:
HcclResult HcclAllReduce(void *sendBuf, void *recvBuf, uint64_t count, HcclDataType dataType, HcclReduceOp op, HcclComm comm, aclrtStream stream)典型调用(AllReduce 求和):
void *sendBuf = nullptr, *recvBuf = nullptr; uint64_t count = 8; size_t mallocSize = count * sizeof(float); aclrtMalloc((void **)&sendBuf, mallocSize, ACL_MEM_MALLOC_HUGE_ONLY); aclrtMalloc((void **)&recvBuf, mallocSize, ACL_MEM_MALLOC_HUGE_ONLY); HcclCommInitRootInfo(rankSize, &rootInfo, deviceId, &hcclComm); aclrtCreateStream(&stream); // 将通信域内所有节点的输入数据相加后,结果发送到所有节点的输出 buffer HcclAllReduce(sendBuf, recvBuf, count, HCCL_DATA_TYPE_FP32, HCCL_REDUCE_SUM, hcclComm, stream); aclrtSynchronizeStream(stream);归约类算子的对齐要求(sendBuf 与 recvBuf 地址):int8 按 1 Byte 对齐;int16、float16、bfp16 按 2 Byte 对齐;int32、float32 按 4 Byte 对齐;int64、uint64、float64 按 8 Byte 对齐。
[!WARNING] 对称内存污染 当通信域注册了对称内存时,AllReduce 过程中部分算法会在 sendBuf 上就地完成归约(read+reduce),导致 sendBuf 中的数据被修改(污染)。因此调用
HcclAllReduce后,sendBuf 中的数据不再作为原始输入使用;如需保留原始输入数据,请在调用前自行备份 sendBuf。
3.4 HcclReduceScatter / HcclReduceScatterV:归约分散
HcclReduceScatter将通信域内所有 rank 的输入数据均分成 rank size 份,取每个 rank 对应编号的一份进行归约操作(sum、prod、max、min),再将结果按编号分散到各个 rank 的输出 buffer:
HcclResult HcclReduceScatter(void *sendBuf, void *recvBuf, uint64_t recvCount, HcclDataType dataType, HcclReduceOp op, HcclComm comm, aclrtStream stream)sendBuf 的数据 size 等于recvCount * rank size,所有 rank 的 recvCount、dataType、op 均应相同,同样存在 sendBuf 就地归约导致的对称内存污染问题。典型调用:
uint32_t rankSize = 8; uint64_t recvCount = 1; uint64_t sendSize = rankSize * recvCount * sizeof(float); uint64_t recvSize = recvCount * sizeof(float); aclrtMalloc(&sendBuf, sendSize, ACL_MEM_MALLOC_HUGE_ONLY); aclrtMalloc(&recvBuf, recvSize, ACL_MEM_MALLOC_HUGE_ONLY); HcclCommInitRootInfo(rankSize, &rootInfo, deviceId, &hcclComm); // 将所有 rank 的 sendBuf 相加后,按 rank_id 顺序均匀分散到各个 rank 的 recvBuf HcclReduceScatter(sendBuf, recvBuf, recvCount, HCCL_DATA_TYPE_FP32, HCCL_REDUCE_SUM, hcclComm, stream); aclrtSynchronizeStream(stream);HcclReduceScatterV与 ReduceScatter 类似,但支持为不同节点配置不同大小的数据量(同一 rank 不同编号的数据大小可设置,不同 rank 间相同编号的数据大小需保持一致),通过sendCounts(第 i 个元素表示向 rank i 发送的数据量)与sendDispls(第 i 个元素表示向 rank i 发送的数据在 sendBuf 中的偏移量)描述:
HcclResult HcclReduceScatterV(void *sendBuf, const void *sendCounts, const void *sendDispls, void *recvBuf, uint64_t recvCount, HcclDataType dataType, HcclReduceOp op, HcclComm comm, aclrtStream stream)当前 rank 编号为 i 时,recvCount 需与 sendCounts 数组中下标 i 的元素值相同;recvBuf 与 sendBuf 地址不能相同。Atlas A3 系列与 Atlas 300I Duo 推理卡仅支持单 Server 场景(后者单 Server 最大 2 张卡即 4 个 NPU),Atlas A2 系列仅支持多机对称分布场景。
3.5 HcclScatter:数据散布
将 root 节点的数据均分并散布至其他 rank:
HcclResult HcclScatter(void *sendBuf, void *recvBuf, uint64_t recvCount, HcclDataType dataType, uint32_t root, HcclComm comm, aclrtStream stream)关键约束:所有 rank 的 recvCount、dataType、root 均应相同;全局只能有 1 个 root 节点;非 root 节点的 sendBuf 可以为空,root 节点的 sendBuf 不能为空;混合组网不支持 Scatter。示例中 root 节点发送数据量为sendCount = rankSize * recvCount:
void *sendBuf = nullptr, *recvBuf = nullptr; uint64_t sendCount = 8, recvCount = 1; size_t sendSize = sendCount * sizeof(float), recvSize = recvCount * sizeof(float); aclrtMalloc(&recvBuf, recvSize, ACL_MEM_MALLOC_HUGE_ONLY); if (device == rootRank) { aclrtMalloc(&sendBuf, sendSize, ACL_MEM_MALLOC_HUGE_ONLY); } HcclCommInitRootInfo(rankSize, &rootInfo, device, &hcclComm); aclrtCreateStream(&stream); // 将通信域内 root 节点的数据均分并散布至其他 rank HcclScatter(sendBuf, recvBuf, recvCount, HCCL_DATA_TYPE_FP32, rootRank, hcclComm, stream); aclrtSynchronizeStream(stream);3.6 HcclAlltoAll / HcclAlltoAllV / HcclAlltoAllVC:全交换
HcclAlltoAll向通信域内所有 rank 发送相同数据量的数据,并从所有 rank 接收相同数据量的数据。输入数据在特定维度切分成块后按顺序发送给其他 rank,同时从其他 rank 接收数据并按顺序拼接:
HcclResult HcclAlltoAll(const void *sendBuf, uint64_t sendCount, HcclDataType sendType, const void *recvBuf, uint64_t recvCount, HcclDataType recvType, HcclComm comm, aclrtStream stream)recvCount 需与 sendCount 取值相同、recvType 需与 sendType 取值相同;recvBuf 与 sendBuf 地址不能相同且内存范围不能重叠。调用时按每个 rank 的份数切分,例如 8 rank、每份 1 个元素:HcclAlltoAll(sendBuf, perCount, HCCL_DATA_TYPE_FP32, recvBuf, perCount, HCCL_DATA_TYPE_FP32, hcclComm, stream)。
HcclAlltoAllV支持可定制的数据量,收发布局由四组 uint64 数组描述:
HcclResult HcclAlltoAllV(const void *sendBuf, const void *sendCounts, const void *sdispls, HcclDataType sendType, const void *recvBuf, const void *recvCounts, const void *rdispls, HcclDataType recvType, HcclComm comm, aclrtStream stream)sendCounts[i] = n:本 rank 发给 rank i 的数据量为 n(单位由 sendType 决定)。sdispls[i] = n:发给 rank i 的数据在 sendBuf 中的起始偏移量(以 sendType 为基本单位)。recvCounts[i] = n:本 rank 从 rank i 收到的数据量为 n。rdispls[i] = n:从 rank i 收到的数据存放在 recvBuf 中的起始偏移量(以 recvType 为基本单位)。
std::vector<uint64_t> sendCounts(rankSize, 1), recvCounts(rankSize, 1); std::vector<uint64_t> sdispls(rankSize), rdispls(rankSize); for (size_t i = 0; i < rankSize; ++i) { sdispls[i] = i; rdispls[i] = i; } HcclAlltoAllV(sendBuf, sendCounts.data(), sdispls.data(), HCCL_DATA_TYPE_FP32, recvBuf, recvCounts.data(), rdispls.data(), HCCL_DATA_TYPE_FP32, hcclComm, stream);HcclAlltoAllVC相比 AlltoAllV,通过输入参数sendCountMatrix一次性传入所有 rank 的收发参数,省去了 recvCounts/rdispls 数组:
HcclResult HcclAlltoAllVC(const void *sendBuf, const void *sendCountMatrix, HcclDataType sendType, const void *recvBuf, HcclDataType recvType, HcclComm comm, aclrtStream stream)sendCountMatrix为形状[rankSize][rankSize]的二维 uint64 数组,sendCountMatrix[i][j] = n表示 rank i 发给 rank j 的数据量为 n:
std::vector<uint64_t> sendCountMatrix(rankSize * rankSize); for (uint32_t i = 0; i < rankSize; ++i) for (uint32_t j = 0; j < rankSize; ++j) sendCountMatrix[i * rankSize + j] = count / rankSize; HcclAlltoAllVC(sendBuf, sendCountMatrix.data(), HCCL_DATA_TYPE_FP32, recvBuf, HCCL_DATA_TYPE_FP32, hcclComm, stream);[!TIP] 性能提示 AlltoAll / AlltoAllV / AlltoAllVC 的性能与 NPU 之间共享数据的缓存区大小有关:当通信数据量超过缓存区大小时性能将明显下降。若业务中 AlltoAll 系列通信数据量较大,建议通过配置环境变量 HCCL_BUFFSIZE 适当增大缓存区大小以提升通信性能。
此外,针对 Atlas 训练系列产品(910),AlltoAll 与 AlltoAllV 的通信域需满足:单 Server 1p、2p 通信域要在同一个 cluster 内(Server 内 0-3 卡和 4-7 卡各为一个 cluster),单 Server 4p、8p 和多 Server 通信域中 rank 要以 cluster 为基本单位,且 Server 间 cluster 选取要一致;单 Server 场景下要求网卡状态为 "up",否则接口执行失败。Atlas 300I Duo 推理卡仅支持单 Server 场景(单 Server 最大 2 张卡即 4 个 NPU)。
四、点对点通信算子详解(3 个)
HCCL 提供不同粒度的点对点通信接口:单 rank 到单 rank 的单收单发接口,以及多个 rank 之间的批量收发接口,详见点对点通信文档。
4.1 HcclSend / HcclRecv:同步单收单发
HcclSend将当前节点指定位置的数据发送至目的节点,HcclRecv从源节点接收数据到当前节点的指定位置:
HcclResult HcclSend(void* sendBuf, uint64_t count, HcclDataType dataType, uint32_t destRank, HcclComm comm, aclrtStream stream) HcclResult HcclRecv(void* recvBuf, uint64_t count, HcclDataType dataType, uint32_t srcRank, HcclComm comm, aclrtStream stream)关键约束:HcclSend 与 HcclRecv 采用同步调用方式,且必须配对使用——一个进程调用 HcclSend 后,需等到与之配对的 HcclRecv 接收数据后,才可进行下一个接口调用;destRank/srcRank等于本 rank 时(自发自收/自收自发)不被支持。经典的对偶收发示例(偶数卡发送、奇数卡接收):
if (deviceId % 2 == 0) { aclrtMalloc(&sendBuf, mallocSize, ACL_MEM_MALLOC_HUGE_ONLY); aclrtMemcpy(sendBuf, mallocSize, hostBuf, mallocSize, ACL_MEMCPY_HOST_TO_DEVICE); HcclSend(sendBuf, count, HCCL_DATA_TYPE_FP32, deviceId + 1, hcclComm, stream); } else { aclrtMalloc(&recvBuf, mallocSize, ACL_MEM_MALLOC_HUGE_ONLY); HcclRecv(recvBuf, count, HCCL_DATA_TYPE_FP32, deviceId - 1, hcclComm, stream); } aclrtSynchronizeStream(stream);4.2 HcclBatchSendRecv:异步批量收发
调用一次HcclBatchSendRecv即可完成本 rank 上的多个收发任务,本 rank 的发送和接收之间是异步的、互不阻塞:
HcclResult HcclBatchSendRecv(HcclSendRecvItem* sendRecvInfo, uint32_t itemNum, HcclComm comm, aclrtStream stream)sendRecvInfo:本 rank 需要下发的收发任务列表首地址,元素类型为HcclSendRecvItem。itemNum:本 rank 需要接收和发送的任务个数。
HcclSendRecvItem以聚合初始化方式构造,例如同时“发给下一节点、接收上一节点”的环形收发:
uint32_t next = (deviceId + 1) % count; uint32_t prev = (deviceId - 1 + count) % count; HcclSendRecvItem sendRecvInfo[2]; sendRecvInfo[0] = HcclSendRecvItem{HCCL_SEND, sendBuf, count, HCCL_DATA_TYPE_FP32, next}; sendRecvInfo[1] = HcclSendRecvItem{HCCL_RECV, recvBuf, count, HCCL_DATA_TYPE_FP32, prev}; HcclBatchSendRecv(sendRecvInfo, 2, hcclComm, stream);约束要点:这里的“异步”指同一张卡上的接收和发送任务互不阻塞;但卡间收发任务依然是同步的,因此与 HcclSend/HcclRecv 一样,卡间收发必须一一对应。针对 Atlas A2 训练系列/推理系列产品,在大规模集群下(ranksize > 500)使用此接口时,并发执行数不能超过 3 个。针对 Atlas 200T A2 Box16 异构子框,若 Server 内卡间出现建链失败(错误码 EI0010),可配置export HCCL_INTRA_ROCE_ENABLE=1、export HCCL_INTRA_PCIE_ENABLE=0,让 Server 内采用 RoCE 环路进行多卡间通信(需确保 Server 上存在 RoCE 网卡,且具有 send/recv 收发关系的设备之间 RDMA 链路互通)。
五、各算子数据类型与归约操作支持速查
不同的产品型号对数据类型与归约操作的支持范围不同,下表汇总了各算子的支持情况,可作为选型与移植的依据。
归约类集合算子(AllReduce / Reduce / ReduceScatter)数据类型
| 产品型号 | 支持数据类型 |
|---|---|
| Ascend 950PR / Ascend 950DT | int8、int16、int32、int64、uint64、float16、float32、float64、bfp16 |
| Atlas A3 训练系列 / A3 推理系列 | int8、int16、int32、int64、float16、float32、bfp16 |
| Atlas A2 训练系列 / A2 推理系列 | int8、int16、int32、int64、float16、float32、bfp16(int64 性能有一定劣化) |
| Atlas 训练系列(910) | int8、int32、int64、float16、float32 |
| Atlas 300I Duo 推理卡 | int8、int16、int32、float16、float32 |
ReduceScatterV 数据类型:Ascend 950 / Atlas A3 支持 int8、int16、int32、int64、float16、float32、bfp16;Atlas A2 支持 int8、int16、int32、float16、float32、bfp16;Atlas 300I Duo 推理卡仅支持 int16、float16、float32。
非归约集合算子(Broadcast / AllGather / AllGatherV / Scatter / AlltoAll / AlltoAllV / AlltoAllVC)与点对点算子(Send / Recv / BatchSendRecv)数据类型
| 产品型号 | 支持数据类型 |
|---|---|
| Ascend 950PR / Ascend 950DT | int8、uint8、int16、uint16、int32、uint32、int64、uint64、float8-e5m2、float8-e4m3、float8-e8m0、hifloat8、float16、float32、float64、bfp16 |
| Atlas A3 训练系列 / A3 推理系列 | int8、uint8、int16、uint16、int32、uint32、int64、uint64、float16、float32、float64、bfp16 |
| Atlas A2 训练系列 / A2 推理系列 | 同 Atlas A3 |
| Atlas 训练系列(910) | int8、uint8、int16、uint16、int32、uint32、int64、uint64、float16、float32、float64 |
| Atlas 300I Duo 推理卡 | 同 Atlas 训练系列(910) |
归约操作(HcclReduceOp)支持情况
| 产品型号 | AllReduce / Reduce / ReduceScatter | ReduceScatterV |
|---|---|---|
| Ascend 950PR / Ascend 950DT | sum、prod、max、min(prod 不支持 int16、bfp16) | sum、prod、max、min(prod 不支持 int16、bfp16) |
| Atlas A3 / A2 系列 | sum、prod、max、min(prod 不支持 int16、bfp16) | sum、max、min |
| Atlas 训练系列(910) | sum、prod、max、min | 不支持该算子 |
| Atlas 300I Duo 推理卡 | sum、prod、max、min(prod、max、min 不支持 int16) | 仅 sum |
[!NOTE] 说明 不同算子在不同型号上的产品支持情况(如 Broadcast 在 Atlas 推理系列不支持、AllGatherV 在 Atlas 训练系列 910 不支持、ReduceScatterV 在 Atlas 训练系列 910 不支持等),请以各算子独立文档的“产品支持情况”章节为准,对应文档见 docs/zh/api_ref/comm_op_interface 下的各算子页面。
六、MC2 自定义算子框架接口
除常规通信算子外,HCCL 还通过 include/hccl_mc2.h 提供 MC2(Kernel Fusion Custom)自定义算子框架接口,用于算子融合场景下构造通信资源上下文,包括:
- 参数对象分配/释放:
HcclKfcAllocOpArgs、HcclKfcFreeOpArgs; - 参数对象设置:
HcclKfcOpArgsSetSrcDataType、HcclKfcOpArgsSetDstDataType、HcclKfcOpArgsSetReduceType、HcclKfcOpArgsSetCount、HcclKfcOpArgsSetAlgConfig、HcclKfcOpArgsSetCommEngine; - 通信资源上下文创建:
HcclCreateOpResCtx(HcclComm comm, uint8_t opType, void* opArgs, void** opResCtx)。
使用流程为:先用HcclKfcAllocOpArgs分配HcclOpArgs参数对象,再通过各HcclKfcOpArgsSet*接口逐项设置源/目的数据类型、归约类型、数据量、算法配置与通信引擎,最后调用HcclCreateOpResCtx基于通信域创建算子资源上下文,供融合算子下发使用。
七、常见陷阱与实战建议
综合上述接口约定,在实际开发中请重点核对以下几点:
- 参数一致性:集合通信要求所有 rank 的数据量(count / sendCount / recvCount 等)、数据类型(dataType / sendType / recvType)、归约操作(op)、root 等关键参数完全相同,否则将导致通信错乱或返回
HCCL_E_PARA。 - 地址约束:AllGatherV、ReduceScatterV、AlltoAll 系列的 recvBuf 与 sendBuf 不能是同一地址(AlltoAll 系列还要求两者内存范围不重叠);Scatter 的 root 节点 sendBuf 不能为空,非 root 节点的 sendBuf 可以为空。
- 内存对齐:归约类算子的输入输出地址须按数据类型对齐——int8 按 1 Byte、int16/float16/bfp16 按 2 Byte、int32/float32 按 4 Byte、int64/uint64/float64 按 8 Byte。
- 对称内存污染:通信域注册对称内存后,AllReduce、ReduceScatter 可能就地修改 sendBuf,需按“调用后不再使用原始输入、必要时提前备份”的原则处理。
- 下发纪律:每个 Device 上所有通信算子必须串行下发,不允许乱序、多线程并发下发或线程重入;同一 Device 上同一通信域内所有算子的下发线程需使用相同 Context。
- 性能调优:AlltoAll 系列大流量场景适当调大 HCCL_BUFFSIZE;P2P 收发注意同步配对语义,批量场景优先使用 HcclBatchSendRecv 减少调用次数。
- 场景限制:部分算子/型号存在单 Server 或对称分布限制(如 AllGatherV、ReduceScatterV 在 A2 仅支持多机对称分布、在 A3 与 300I Duo 仅支持单 Server),移植前先核对目标型号的“产品支持情况”。
更完整的算子文档、数据类型定义索引与构建方式,可继续阅读仓库内的 通信算子接口 README、头文件与库文件说明、数据类型定义 以及 构建指南;可运行示例见 examples/01_point_to_point 与 examples/02_collectives 目录。
【免费下载链接】hccl集合通信库(Huawei Collective Communication Library,简称HCCL)是基于昇腾AI处理器的高性能集合通信库,为计算集群提供高性能、高可靠的通信方案项目地址: https://gitcode.com/cann/hccl
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考