HCCL HcclSend 点对点发送接口:参数详解、同步约束与源码实现剖析 HCCL HcclSend 点对点发送接口参数详解、同步约束与源码实现剖析【免费下载链接】hccl集合通信库Huawei Collective Communication Library简称HCCL是基于昇腾AI处理器的高性能集合通信库为计算集群提供高性能、高可靠的通信方案项目地址: https://gitcode.com/cann/hccl本文以 HCCL 点对点通信接口HcclSend为核心完整讲解其函数原型、参数语义、各产品型号支持的数据类型、返回值与调用约束并结合 HCCL 仓库中 send 算子源码、Send 算法选择器 和 send_recv 官方示例帮助开发者掌握从接口调用、底层执行路径到可运行样例验证的完整链路。产品支持情况HcclSend属于 HCCL 点对点通信P2P算子各硬件平台的支持情况如下与 HcclSend 接口文档 保持一致产品支持情况Ascend 950PR / Ascend 950DT支持Atlas A3 训练系列产品 / Atlas A3 推理系列产品支持Atlas A2 训练系列产品 / Atlas A2 推理系列产品支持Atlas 推理系列产品不支持Atlas 训练系列产品支持需要特别注意Atlas 推理系列产品不支持 HcclSend。推理侧部署时如需点对点数据搬运应结合具体型号确认支持算子列表可参考 算子支持列表 目录下各产品的支持矩阵文档。功能说明与函数原型HcclSend是点对点通信 Send 操作接口将当前节点指定位置Device 内存的数据发送至目的节点。接口声明位于 hccl.hHcclResult HcclSend(void* sendBuf, uint64_t count, HcclDataType dataType, uint32_t destRank, HcclComm comm, aclrtStream stream)参数说明参数名输入/输出描述sendBuf输入源数据 buffer 地址Device 侧内存。count输入发送数据的个数元素个数非字节数。dataType输入发送数据的数据类型HcclDataType类型。不同型号支持的数据类型不同详见下文。destRank输入通信域内数据接收端的 rank 编号。comm输入集合通信操作所在的通信域HcclComm句柄。stream输入本 rank 所使用的任务流aclrtStream。数据类型说明不同硬件平台支持的数据类型范围不同平台支持的数据类型Ascend 950PR / Ascend 950DTint8、uint8、int16、uint16、int32、uint32、int64、uint64、float8-e5m2、float8-e4m3、float8-e8m0、hifloat8、float16、float32、float64、bfp16Atlas A3 训练系列 / Atlas A3 推理系列int8、uint8、int16、uint16、int32、uint32、int64、uint64、float16、float32、float64、bfp16Atlas A2 训练系列 / Atlas A2 推理系列int8、uint8、int16、uint16、int32、uint32、int64、uint64、float16、float32、float64、bfp16Atlas 训练系列int8、uint8、int16、uint16、int32、uint32、int64、uint64、float16、float32、float64可见 950 系列额外支持多种 float8 变体与 hifloat8Atlas A2/A3 系列额外支持 bfp16而老款 Atlas 训练系列仅支持常规整型与浮点类型。类型定义可进一步查阅 数据类型说明文档。返回值与错误码语义接口返回HcclResult具体取值如下返回值说明HCCL_SUCCESS接口调用成功。HCCL_E_PTR传入的指针参数为空如 comm、sendBuf 等为 nullptr。HCCL_E_PARA传入的参数无效如 count 超过上限、destRank 越界等。HCCL_E_NOT_SUPPORT操作不被支持如 dataType 非法或当前型号不支持、destRank 等于本 rank 时不支持自发自收等。HCCL_E_INTERNAL内部错误。这些错误语义在源码中可以得到逐条印证。send.cc 中的GetAndCheckSendPara完成了参数校验RPT_INPUT_ERR( comm nullptr, EI0003, std::vectorstd::string({ccl_op, value, parameter, expect}), std::vectorstd::string({HcclSend, nullptr, comm, non-null pointer})); CHK_PTR_NULL(comm); RPT_INPUT_ERR( sendBuf nullptr, EI0003, ...); CHK_PTR_NULL(sendBuf); CHK_RET(CheckCount(count)); CHK_RET(CheckDataType(dataType, false)); CHK_RET(HcclGetRankSize(comm, rankSize)); CHK_RET(HcclGetRankId(comm, userRank)); CHK_PRT_RET( userRank destRank, HCCL_ERROR([HcclSend] destRank cannot be equal to self.), HcclResult::HCCL_E_NOT_SUPPORT);可以看到comm、sendBuf为 nullptr 时触发空指针检查对应HCCL_E_PTR并通过RPT_INPUT_ERR输出 EI0003 错误码便于诊断CheckCount/CheckDataType分别校验数据个数上限与类型合法性对应HCCL_E_PARA/HCCL_E_NOT_SUPPORTdestRank等于本 rank 时直接返回HCCL_E_NOT_SUPPORT即不支持自发自收HcomCheckUserRank会再次校验 userRank 与 destRank 均在通信域 rankSize 范围内对应 destRank 越界的HCCL_E_PARA。另外值得注意的是 send.cc 中对count 0的处理会打印 WARNING 并直接返回 HCCL_SUCCESS即空发送被视作成功空操作这是排查发送没数据但没报错类问题时的关键线索。同步调用与配对约束HcclSend与HcclRecv接口采用同步调用方式且必须配对使用一个进程调用HcclSend接口后需要等到与之配对的HcclRecv接口接收数据后才可以进行下一个接口调用。此外还有两条 Device 侧约束多个通信域下的所有通信算子在每个 Device 上需要保证串行下发不允许乱序、多线程并发下发也不支持线程重入在同一 Device 上同一通信域内的所有通信算子的下发线程需要使用相同的 Context。工程实践中这意味着发送方和接收方必须严格一次一发一收配对接收方的HcclRecv调用顺序、destRank/srcRank编号必须与发送方约定一致否则会因对端长期不配对而造成阻塞多线程程序应为每个 Device 使用独立线程并在该线程内完成本 Device 的全部 HCCL 调用不要跨线程并发向同一 Device 下发通信算子调用完成后应通过aclrtSynchronizeStream(stream)等待任务流中的通信任务真正执行完成再读取接收缓冲区。源码剖析从 HcclSend 到执行器从 send.cc 看HcclSend入口并非直接执行而是先做一次执行路径分派HcclResult HcclSend(void* sendBuf, uint64_t count, HcclDataType dataType, uint32_t destRank, HcclComm comm, aclrtStream stream) { HCCL_INFO([HcclSend] Start.); if (IsHostDpu(comm)) { return HcclSendNext(sendBuf, count, dataType, destRank, comm, stream); } if (GetHcommVersion() CANN_VERSION(9, 0, 0)) { return HcclSendInner(sendBuf, count, dataType, destRank, comm, stream); } bool isOutPlace false; CHK_RET(IsOutPlaceDevice(isOutPlace)); if (!isOutPlace) { return HcclSendInner(sendBuf, count, dataType, destRank, comm, stream); } return HcclSendNext(sendBuf, count, dataType, destRank, comm, stream); }可以推断出三条分派规则通信域运行在 Host DPU 上时走新流程HcclSendNext底层 HComm 库版本低于 9.0.0 时走老流程HcclSendInner非 Out-Place 设备即 HCCL 运行在 NPU 本侧走老流程Out-Place 设备走新流程。新流程HcclSendNext的主链路为InitEnvConfig→ 参数校验上一节的GetAndCheckSendPara→SendEntryLog接口交互日志 → SendExec。SendExec内部会构建OpParamGenerateSendOpParam中计算dataSize count * 类型字节数、写入sendRecvRemoteRank destRank等随后依次完成rankSize 1时进入单 rank 处理SingleRankProc并告警调用Selector根据拓扑选择算法调用HcclExecOp下发执行。算法选择器AIC / AIV / DPU 三条路线Send 算子的自动选择器实现在 send_auto_selector.cc通过REGISTER_SELECTOR_BY_OPTYPE(HcclCMDType::HCCL_CMD_SEND, 18, SendAutoSelector)注册。三类设备的选择逻辑清晰可查执行引擎选择方法选中的算法备注AICAI CPU 通信引擎SelectAicpuAlgoAicpuSendSoleMesh无条件匹配AIVSelectAivAlgoAivSendSoleMeshtopoInfo-level2UbRtp为真或拓扑层级数 ≥ 3 时不匹配回退默认DPUSelectDPUAlgoDpuSendSoleHost或DpuSendSoleMesh从最高 netLayer 逐级查找本 rank 与 destRank 间的链路若链路端点为 host nic → device nic 场景则选DpuSendSoleHost否则选DpuSendSoleMesh从源码结构看AIV 路线的模板与内核位于 template/aiv/kernelDPU 路线的模板位于 template而 host_nic 专用模板 正对应选择器中的DpuSendSoleHost场景。执行器实现则位于 algorithm/executor其中InsV2SendSoleExecutor的资源计算固定申请单通道resourceRequest.channels.resize(1)符合单发单收一对一传输的资源模型。此外op_graph/send_proto.cc 与HcclSendGraphMode提供了图模式OFFLOAD下的 Send 下发入口供框架做算子 offload 时使用。示例实战8 卡 Send/Recv 收发验证仓库提供了可直接编译运行的完整示例 examples/01_point_to_point/01_send_recv其场景与接口文档中的调用示例完全对应8 个 NPU 设备、偶数卡0/2/4/6发送、奇数卡1/3/5/7接收。环境准备# 设置 CANN 环境变量以 root 用户默认安装路径为例 source /usr/local/Ascend/cann/set_env.sh核心代码main.cc 的关键片段// 初始化集合通信域 HcclComm hcclComm; HCCLCHECK(HcclCommInitRootInfo(ctx-devCount, ctx-rootInfo, device, hcclComm)); // 创建任务流 aclrtStream stream; ACLCHECK(aclrtCreateStream(stream)); // 执行 Send/Recv 操作0/2/4/6卡发送数据1/3/5/7接收数据 // HcclSend 与 HcclRecv 接口采用同步调用方式且必须配对使用 if (device % 2 0) { // 申请 Device 内存用于存放输入数据 ACLCHECK(aclrtMalloc(sendBuf, mallocSize, ACL_MEM_MALLOC_HUGE_ONLY)); // 申请 Host 内存用于设置输入数据将内容初始化为 DeviceId void* hostBuf nullptr; ACLCHECK(aclrtMallocHost(hostBuf, mallocSize)); float* tmpHostBuf static_castfloat*(hostBuf); for (uint64_t i 0; i count; i) { tmpHostBuf[i] static_castfloat(device); } ACLCHECK(aclrtMemcpy(sendBuf, mallocSize, hostBuf, mallocSize, ACL_MEMCPY_HOST_TO_DEVICE)); ACLCHECK(aclrtFreeHost(hostBuf)); // 执行 Send 操作 HCCLCHECK(HcclSend(sendBuf, count, HCCL_DATA_TYPE_FP32, device 1, hcclComm, stream)); } else { // 申请 Device 内存用于接收数据 ACLCHECK(aclrtMalloc(recvBuf, mallocSize, ACL_MEM_MALLOC_HUGE_ONLY)); // 执行 Recv 操作 HCCLCHECK(HcclRecv(recvBuf, count, HCCL_DATA_TYPE_FP32, device - 1, hcclComm, stream)); } // 阻塞等待任务流中的集合通信任务执行完成 ACLCHECK(aclrtSynchronizeStream(stream));示例体现了接口文档中约束说明的落地方式发送端的destRank是device 1接收端的srcRank是device - 1两侧严格配对数据在 Host 侧初始化为发起发送的 deviceId再拷入 Device 内存最终奇数卡打印的正是相邻偶数卡的 deviceId形成端到端数据正确性验证每个 Device 在独立线程中完成初始化与收发线程内串行下发满足每个 Device 串行下发约束最后统一aclrtSynchronizeStream同步。编译与运行在 01_send_recv 示例目录 下执行make make test运行结果示例偶数节点将内容为自身 DeviceId 的sendBuf发送至下一个奇数节点Found 8 NPU device(s) available rankId: 1, output: [ 0 0 0 0 0 0 0 0 ] rankId: 3, output: [ 2 2 2 2 2 2 2 2 ] rankId: 5, output: [ 4 4 4 4 4 4 4 4 ] rankId: 7, output: [ 6 6 6 6 6 6 6 6 ]如需指定通信算子的展开模式可参考 HCCL_OP_EXPANSION_MODE 环境变量说明例如# 设置通信算子的展开模式为 AI CPU 通信引擎 export HCCL_OP_EXPANSION_MODEAI_CPU总结HcclSend是 HCCL 点对点通信的基础发送接口使用时需牢记三点参数契约count是元素个数而非字节数destRank必须是对端 rank 且不能等于自身dataType需在当前型号支持范围内见上文各型号类型表调用纪律与HcclRecv同步配对使用、Device 上串行下发、同通信域同 Context完成后用aclrtSynchronizeStream同步底层链路接口入口按 HComm 版本与设备形态分派新老流程随后经GetAndCheckSendPara校验、SendExec组装算子参数再由SendAutoSelector在 AIC/AIV/DPU 三条执行路线中按拓扑选择具体算法最终由对应 executor 下发通信指令。配套的 HcclRecv 接口文档 与 批量收发接口 HcclBatchSendRecv 可结合本文一起阅读覆盖 HCCL 全部点对点通信场景更多点对点接口总览参见 点对点通信文档。【免费下载链接】hccl集合通信库Huawei Collective Communication Library简称HCCL是基于昇腾AI处理器的高性能集合通信库为计算集群提供高性能、高可靠的通信方案项目地址: https://gitcode.com/cann/hccl创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考