Hccl模板参数
功能说明
创建Hccl对象时需要传入模板参数HcclServerType 。
函数原型
Hccl类定义如下,模板参数HcclServerType说明见表1。
1 2 |
template <HcclServerType serverType = HcclServerType::HCCL_SERVER_TYPE_AICPU> class Hccl; |
参数说明
返回值
无
支持的型号
Atlas A2训练系列产品/Atlas 800I A2推理产品
注意事项
无
调用示例
以Add计算+AllReduce通信+Mul计算的任务编排方式为例,辅以代码片段,对本通信API在计算和通信融合的场景下的使用进行说明:
图1 Add计算+AllReduce通信+Mul计算任务编排
// @brief add+allreduce+mul融合算子kernel,
// 任务编排为先进行Add计算,然后将其计算结果作为AllReduce的输入进行ReduceSum操作,
// 最后将AllReduce的结果作为Mul计算的第一个输入,与Mul的第二个输入进行element-wise mul计算,将结果写到cGM输出内存中。
// @param [in] aGM: Add计算的第一个输入对应的GM内存
// @param [in] bGM: Add计算的第二个输入对应的GM内存
// @param [in] mulGM: Mul计算的第二个输入对应的GM内存
// @param [out] cGM: add+allreduce+mul融合计算的输出GM内存
// @param [in] workspaceGM 用于存储中间计算结果的GM内存
// @param [in] tilingGM 存放TilingData的GM内存
extern "C" __global__ __aicore__ void add_all_reduce_mul(
GM_ADDR aGM, GM_ADDR bGM, GM_ADDR mulGM, GM_ADDR cGM, GM_ADDR workspaceGM, GM_ADDR tilingGM)
{
// 假设本Kernel的所有计算操作和通信任务下发都是在AI Cube核完成,AI Vector核退出执行
if (g_CoreType == AIV) { return; }
// 从tilingGM中获取预先准备好的Tiling数据
// 此处假设Add和Mul计算的切分策略一致,即共用一个tiling数据
GET_TILING_DATA(tiling_data, tilingGM);
int tileCnt = tiling_data.tileCnt; // 将1个输入数据切分为tileCnt轮进行计算
int tileLen = tiling_data.tileLen; // 每次计算的数据个数tileLen
// Add计算API的初始化
KernelAdd add_op;
add_op.Init(tileLen, 2);
// step1. 用户创建Hccl客户端对象的创建+初始化
Hccl<HCCL_SERVER_TYPE_AICPU> hccl;
auto contextGM = AscendC::GetHcclContext<HCCL_GOURP_ID_0>(); // AscendC自定义算子框架提供的获取通信上下文的能力,对应的数据结构为:HcclCombinOpParam
hccl.Init(contextGM);
auto aAddr = aGM; // 每次切分计算,Add计算第一个输入参与计算的地址
auto bAddr = bGM; // 每次切分计算,Add计算第二个输入参与计算的地址
auto computeResAddr = workspaceGM; // workspaceGM用来临时存放Add计算的结果,同时作为通信任务的输入地址
auto cAddr = cGM; // cGM先用来存放AllReduce的通信结果,同时作为Mul计算的第一个输入
auto aOffset = tileLen * sizeof(DT_FLOAT16); // 每次切分计算,Add计算第一个输入参与计算的数据size
auto bOffset = tileLen * sizeof(DT_FLOAT16); // 每次切分计算,Add计算第二个输入参与计算的数据size
auto cOffset = tileLen * sizeof(DT_FLOAT16); // 每次切分计算,Add计算结果得到的数据size
HcclHandle hanleIdList[tileCnt];
for (int i = 0; i < tileCnt; i++) {
// step2. 用户调用AllReduce接口,提前通知服务端完成通信任务的组装和下发,该接口返回该通信任务的标识handleId给用户
// PS: 可以将这个通信任务下发在计算开始前生成,这样其任务组装会在计算流水中被掩盖
auto handleId = hccl.AllReduce(computeResAddr, cAddr, tileLen, HCCL_DATA_TYPE_FP16, HCCL_REDUCE_SUM);
hanleIdList[i] = handleId;
// step3 用户开始调用Add计算Api的初始化和计算,并调用SyncAll等待该计算完成
add_op.UpdateAddress(aAddr, bAddr, computeResAddr);
add_op.Process();
// 等待计算任务在所有block上执行完成
SyncAll();
// step4. 当每份切分数据的Add计算完成后,用户即可调用Commit接口通知通信侧可以执行handleId对应的通信任务(异步接口)
hccl.Commit(handleId);
// 更新下一份切分数据的地址
aAddr += aOffset;
bAddr += bOffset;
computeResAddr += cOffset;
cAddr += cOffset;
}
// Mul计算Api对象的创建
KernelMul mul_op;
for (int i = 0; i < tileCnt; i++) {
// step5. 用户在进行mul计算前,需要调用Wait阻塞接口确保对应切分数据的通信执行完毕,即确保mul的第一个输入的数据ready
hccl.Wait(hanleIdList[i]);
SyncAll(); // 核间同步
// mul计算的参数设置,参数分别为:第一个输入的地址、第二个输入的地址、计算结果的地址,一次mul计算的数据个数
mul_op.InitAddress(cAddr, mulAddr, cAddr, tileLen, 1);
// step6. mul计算执行
mul_op.Process();
// 更新下一份切分数据的地址
mulAddr += cOffset;
cAddr += cOffset;
}
// step7. 后续无通信任务编排,用户调用Finalize接口通知服务端执行完通信任务后即可退出
hccl.Finalize();
}
父主题: Hccl