Line data Source code
1 : /**
2 : * Copyright (c) 2025 Huawei Technologies Co., Ltd.
3 : * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4 : * CANN Open Software License Agreement Version 2.0 (the "License").
5 : * Please refer to the License for details. You may not use this file except in compliance with the License.
6 : * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7 : * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8 : * See LICENSE in the root of the software repository for the full text of the License.
9 : */
10 :
11 : #ifndef __AICPU_KFC_DEF_H__
12 : #define __AICPU_KFC_DEF_H__
13 :
14 : #include <cstdint>
15 : #include <chrono>
16 : #include "common/aicpu_hccl_def.h"
17 : #include "hccl_common.h"
18 : #include "hccl_msg.h"
19 : #include "aicpu_operator_pub.h"
20 :
21 : constexpr int32_t AICPU_CNT = 8;
22 : constexpr int32_t CLUSTER_CNT = 2;
23 : constexpr u64 HCCL_COPY_ALIGN = 16 * 1024;
24 : constexpr u64 HCCL_MIN_SLICE_ALIGN = 128;
25 : constexpr u32 AC_DEFAULT_ONE_SHOT_SIZE = 100 * 1024; // 缺省小于100K使用oneshot算法
26 : constexpr s32 AC_ERROR_INVALID_PARAM = 0x011088;
27 : constexpr u32 AICPU_OP_NOTIFY_NUM = 2U;
28 : constexpr u32 AC_SQE_SIZE = 64U;
29 : constexpr u32 AC_DEFAULT_WINDOW_DIM = 2; // 小数据量时分2片做swap window使用,可以提前把下一次内容拷贝到window中
30 : constexpr u32 AC_DEFAULT_RANK_GROUP = 2;
31 : constexpr u32 HCCL_SMALL_COUNT_1_M = 1024 * 1024;
32 : constexpr u32 HCCL_SMALL_COUNT_256K = 256 * 1024; // 256KB: 256 * 1024
33 : constexpr uint8_t MC2_DEBUG_ONLY_CUBE = 1; // 只计算不通信
34 : constexpr uint8_t MC2_DEBUG_PRINT_MSG = 2;
35 : constexpr uint8_t MC2_DEBUG_PRINT_BUFF = 3;
36 : constexpr uint8_t MC2_DEBUG_TIME_TAKEN = 4; // KFC算子自己统计各阶段耗时
37 : constexpr uint8_t MC2_DEBUG_WAIT_COMM = 8; // KFC算子等待通信结束
38 : constexpr uint8_t MC2_DEBUG_PREPARE_TIMEOUT = 250;
39 : constexpr uint8_t MC2_DEBUG_COMMIT_TIMEOUT = 251;
40 : constexpr uint8_t MC2_DEBUG_NOTIFY_WAIT_TIMEOUT = 252;
41 : constexpr uint8_t MC2_DEBUG_AICORE_WAIT_TIMEOUT = 253;
42 : constexpr uint8_t MC2_DEBUG_FINALIZE_TIMEOUT = 254;
43 : constexpr uint8_t MC2_DEBUG_SDMA_ERROR = 255;
44 : constexpr uint64_t MC2_API_MSG_TIMEOUT = 20UL;
45 : constexpr uint32_t MC2_API_XORCHECK_PRINT_NUM = 10000;
46 : const uint16_t TAIL_TASK = 1;
47 : const uint16_t HEAD_TASK = 0;
48 : constexpr int32_t MAX_COMM_CTX_NUM = 3;
49 : constexpr int32_t LOCAL = 0;
50 : constexpr int32_t REMOTE = 1;
51 : constexpr uint16_t MAX_BATCH_WRITE_THREAD_NUM = 2;
52 :
53 : constexpr uint8_t FLAG_OFFSET = 1;
54 : constexpr uint8_t FLAG_INTERVAL = 2;
55 : constexpr uint8_t POST_SEND_FLAG_COUNT = 3;
56 : constexpr u64 MAX_RDMA_WQE_SIZE = 2ULL * 1024 * 1024 * 1024; // RDMA最大WQE限制是2GB
57 :
58 : using HcclHandle = int8_t;
59 :
60 : enum CommAlgType {
61 : COMM_ALG_DEFAULT = 0,
62 : COMM_ALG_FULL_MESH = 1,
63 : COMM_ALG_DOUBLE_RING = 2,
64 : COMM_ALG_SWITCH_WING = 3,
65 : COMM_ALG_RESERVED
66 : };
67 :
68 : enum MC2_BUFFER_TYPE {
69 : MC2_BUFFER_TYPE_DEFAULT = 0,
70 : MC2_BUFFER_TYPE_OUTPUT,
71 : MC2_BUFFER_TYPE_WINDOW_IN,
72 : MC2_BUFFER_TYPE_WINDOW_OUT,
73 : MC2_BUFFER_TYPE_WORKSPACE,
74 : MC2_BUFFER_TYPE_INPUT,
75 : MC2_BUFFER_TYPE_COMMOUT,
76 : MC2_BUFFER_TYPE_END
77 : };
78 :
79 : enum AicpuTilingVer {
80 : TILING_DATA_VER_OLD_FOR_HOST = 0,
81 : TILING_DATA_VER_OLD_FOR_KERNEL,
82 : TILING_DATA_VER_OLD_FOR_KERNEL_V2,
83 : TILING_DATA_VER_FOR_TILING_API = 100
84 : };
85 :
86 : struct KFCGroupTilingDataAuto { // for grouped_mat_mul_all_reduce op
87 : HcclKFCTilingData msg[64]; // 64: same as the tiling data size
88 : uint32_t groupNum;
89 : uint32_t groupTilingMagicNum;
90 : };
91 :
92 : struct KFCGroupTilingData { // for grouped_mat_mul_all_reduce op
93 : uint32_t groupNum;
94 : uint32_t reserve;
95 : HcclKFCTilingData msg[64]; // 64: same as the tiling data size
96 : };
97 :
98 : struct KFCTask {
99 : u64 inputA; // A矩阵地址,通信在前时为sendbuffer
100 : u64 outputC; // 输出C矩阵地址
101 : u64 commOut; // 双输出时,通信输出地址
102 : u64 context; // HCCL通信context
103 : u64 workSpace; // 通信结果不直接输出时,放到workspace中
104 : u64 tilingData; // 通信
105 : };
106 :
107 : struct KFCTaskV2 {
108 : u64 inputA; // A矩阵地址,通信在前时为sendbuffer
109 : u64 outputC; // 输出C矩阵地址
110 : u64 commOut; // 双输出时,通信输出地址
111 : u64 ctxNum;
112 : u64 context[MAX_COMM_CTX_NUM]; // HCCL通信context
113 : u64 workSpace; // 通信结果不直接输出时,放到workspace中
114 : u64 tilingData; // 通信
115 : };
116 :
117 : struct KFCResInitTask {
118 : u64 context; // A矩阵地址,通信在前时为sendbuffer
119 : bool isCustom;
120 : };
121 :
122 : struct PostSendTaskParam {
123 : // For DataCopy
124 : u32 lKey;
125 : u32 rKey;
126 : HcclQpInfoV2 qpInfo;
127 : u64 remoteAddr;
128 : u64 localAddr;
129 : u64 dataSize;
130 :
131 : u64 timeOut;
132 :
133 : // For Flag
134 : u64 localFlagAddr;
135 : u64 remoteFlagAddr;
136 : u32 lfKey;
137 : u32 rfKey;
138 : };
139 :
140 : struct CommonHcclMsg {
141 : HcclCMDType commType; // 通信原语类型,AllReduce/AllGather.../Finalize/InterHcclGroupSync
142 : HcclReduceOp opType; // reduce操作类型,sum/prod/max/min
143 : uint64_t sendBuffer; // 源数据buffer地址。
144 : uint64_t recvBuffer; // 目的数据buffer地址
145 : uint64_t dataCnt; // 参与操作的数据个数
146 : uint64_t strideCount; // 完整的数据结果一般是连续的,切分多轮后会导致需要加上stride,例如AllGather的stride是每个卡上的完整数据量
147 : HcclDataType hcclDataType; // 参与操作的数据类型
148 : uint32_t p2pSrcDestRankId; // 点对点通信send/recv对端的rankId,send中的destRank, recv中的srcRank
149 : uint32_t valid; // 检查消息有效性
150 : uint8_t repeatCnt; // 本消息需要重复的次数,默认是1
151 : uint8_t everyTurnRsp; // 每轮都需要等待执行结束发送响应,再执行下一轮
152 : uint8_t everyTurnWait; // 每轮都需要等待work消息再执行
153 : HcclHandle commDepGroupID; // 本消息执行需要等待的通信域组id,默认是-1,表示不需要等待,用于设置notify监听的通信域组id
154 : HcclHandle commDepHandleID; // 本消息执行需要等待的通信域轮次,默认是-1,表示不需要等待,用于设置notify监听的地址
155 : HcclHandle selfHandleID; // 通信消息对应的handleId值
156 : uint8_t seqNum; // 消息序号
157 : HcclApi::HcclTilingVersion version; // 消息的版本信息,version=0使用hcclMsg
158 : uint32_t xorCheck; // xor checksum
159 : uint64_t ccOpTilingData; // 消息的tiling信息
160 0 : void PrintMsg(const std::string &desc) {
161 0 : HCCL_INFO("%s Msg[version %u, commType %u, opType %u, sendBuffer %p, recvBuffer %p, dataCnt %lu, strideLen %lu,"
162 : " hcclDataType %u, p2pSrcDestRankId %u, valid %u"
163 : " repeatCnt %u, everyTurnRsp %u, everyTurnWait %u, commDepGroupID %d,"
164 : " commDepHandleID %d, selfHandleID %d, seqNum %u, ccOpTilingData %#llx]",
165 : desc.c_str(), static_cast<uint32_t>(version), static_cast<uint32_t>(commType),
166 : static_cast<uint32_t>(opType), sendBuffer, recvBuffer, dataCnt, strideCount,
167 : static_cast<uint32_t>(hcclDataType), p2pSrcDestRankId, valid, repeatCnt, everyTurnRsp, everyTurnWait,
168 : commDepGroupID, commDepHandleID, selfHandleID, seqNum, ccOpTilingData);
169 0 : }
170 : };
171 :
172 : struct WqeSendSharedContect {
173 : volatile u32 startedThreadNum = 0;
174 : volatile u32 workedThreadNum = 0;
175 : std::atomic<bool> taskFinishFlag{false};
176 : volatile u32 curThreadIdsOnCpu[AICPU_CNT];
177 : volatile u32 sendWqeNum[MAX_BATCH_WRITE_THREAD_NUM];
178 : };
179 :
180 : struct DataBlock {
181 : uint32_t data[16];
182 : };
183 :
184 : constexpr uint32_t MAX_AICPU_NUM_BLOCKS = 6U;
185 :
186 : // HCCL 代码直调时直接传此结构:
187 6 : struct AivAicpuOpParam {
188 : HcclCMDType commType; // 32b
189 : HcclReduceOp opType; // 32b
190 : u64 sendBuffer;
191 : u64 recvBuffer;
192 : u64 count;
193 : u64 strideLen;
194 :
195 : // offset 32B
196 : HcclDataType hcclDataType;
197 :
198 : uint32_t valid; // 检查消息有效性
199 : uint8_t isLast; // 是否最后一个下
200 : uint8_t funID; // 功能ID,1地址消息; 2开始工作
201 : uint8_t sendCnt; // 发送计数
202 : uint8_t rcvCnt; // 执行结束轮次技术
203 : uint8_t everyTurnRsp; // 每轮都需要等待执行结束发送响应,再执行下一轮
204 : uint8_t everyTurnWait; // 每轮都需要等待work消息再执行
205 : uint8_t totalTurnCnt; // 总轮次
206 : uint8_t useBufferType;
207 : uint64_t winOffset; // 发送数据偏移地址
208 :
209 : HcclOpIdentifier opId;
210 : uint8_t res[2]; // 整体消息64字节
211 125 : void PrintMsg(const std::string &desc) {
212 125 : HCCL_INFO("%s Msg[commType %u, opType %u, sendBuffer %p, recvBuffer %p, count %lu, strideLen %lu,"
213 : " hcclDataType %s, valid %u, isLast %u, funID %u, sendCnt %u, rcvCnt %u,"
214 : " everyTurnRsp %u, everyTurnWait %u, totalTurnCnt %u, winOffset %lu]",
215 : desc.c_str(), static_cast<uint32_t>(commType), static_cast<uint32_t>(opType), sendBuffer,
216 : recvBuffer, count, strideLen, GetDataTypeEnumStr(hcclDataType).c_str(), valid, isLast,
217 : funID, sendCnt, rcvCnt, everyTurnRsp, everyTurnWait, totalTurnCnt, winOffset);
218 125 : }
219 : };
220 :
221 : constexpr uint32_t MAX_DEBUG_CNT = 128U;
222 : struct AicDebugCntInfo {
223 : uint8_t cnt[MAX_DEBUG_CNT];
224 : }; // 128
225 :
226 : using AicpuAddOneNotifyWaitSqe = void (*)(uint16_t, uint16_t, u64, const uint8_t *, uint8_t *,
227 : const dfx::DfxTimeOutConfig &);
228 : using AicpuAddOneRecordSqe = void(*)(uint16_t, uint16_t, u64, const uint8_t *, uint8_t *);
229 : using AicpuAddOneWriteValueRecordSqe = void(*)(uint16_t, uint16_t, u64, const uint8_t *, uint8_t *);
230 : using AicpuAddOneMemcpySqe = void(*)(uint16_t, uint16_t, const void *, uint32_t, const aclDataType,
231 : aclrtReduceKind, const void *, uint32_t, uint32_t, uint32_t, u64, uint8_t, const uint8_t *, uint8_t *, uint32_t);
232 : using AicpuAddOneEventResetSqe = void(*)(uint16_t, int32_t, uint16_t, int64_t, int64_t,
233 : u64, const uint8_t *, uint8_t *);
234 : using AicpuAddOneEventRecordSqe = void(*)(uint16_t, int32_t, uint16_t, const uint8_t *, uint8_t *);
235 : using AicpuAddOneEventWaitSqe = void(*)(uint16_t, int32_t, uint16_t, const uint8_t *, uint8_t *);
236 : using AicpuAddOneRdmaDbSendSqe = void(*)(uint16_t, uint16_t, uint64_t, uint64_t,
237 : uint32_t, uint8_t, const uint8_t *, uint8_t *);
238 : using AicpuAddOneFlipPlaceHolderSqe = void(*)(uint16_t, uint16_t, uint16_t, const uint8_t *, uint8_t *);
239 :
240 : extern AicpuAddOneNotifyWaitSqe AicpuGetAddOneNotifyWaitSqe();
241 : extern AicpuAddOneRecordSqe AicpuGetAddOneRecordSqe();
242 : extern AicpuAddOneWriteValueRecordSqe AicpuGetAddOneWriteValueRecordSqe();
243 : extern AicpuAddOneMemcpySqe AicpuGetAddOneMemcpySqe();
244 : extern AicpuAddOneEventResetSqe AicpuGetAddOneEventResetSqe();
245 : extern AicpuAddOneEventRecordSqe AicpuGetAddOneEventRecordSqe();
246 : extern AicpuAddOneEventWaitSqe AicpuGetAddOneEventWaitSqe();
247 : extern AicpuAddOneRdmaDbSendSqe AicpuGetAddOneRdmaDbSendSqe();
248 : extern AicpuAddOneFlipPlaceHolderSqe AicpuGetAddOneFlipPlaceHolderSqe();
249 :
250 : struct RestartParam {
251 : // 重执行标记,表示是否发生异常需要重执行
252 : bool restartFlag = false;
253 : // 重执行次数
254 : uint32_t restartCnt = 0;
255 : // 是否所有通信域都重执行协商完成
256 : uint32_t consultationAllEnd = 0;
257 : // 通信域重执行协商情况
258 : bool consultationResult[MAX_COMM_CTX_NUM] = {false, false, false};
259 : // 通信域是否执行过changeLink
260 : bool linkChanged[MAX_COMM_CTX_NUM] = {false, false, false};
261 : // 通信域重执行协商初始化state
262 : HcclOpExecFSM fsmState[MAX_COMM_CTX_NUM] = {HcclOpExecFSM::HCCL_OP_EXEC_FSM_WAIT_END,
263 : HcclOpExecFSM::HCCL_OP_EXEC_FSM_WAIT_END,
264 : HcclOpExecFSM::HCCL_OP_EXEC_FSM_WAIT_END};
265 : KfcError errorCode[MAX_COMM_CTX_NUM] = {KfcError::kNone, KfcError::kNone, KfcError::kNone};
266 : std::chrono::time_point<std::chrono::steady_clock> startTime[MAX_COMM_CTX_NUM];
267 : };
268 :
269 : enum class BarrierStatus: u8 {
270 : NO_BARRIER = 0U,
271 : SELF_BARRIER,
272 : INTER_BARRIER
273 : };
274 :
275 : struct BarrierInfo {
276 : BarrierStatus status;
277 : u64 lastTimeStamp;
278 : };
279 :
280 : enum class AicpuServerRole {
281 : MASTER = 0,
282 : SLAVE = 1,
283 : INVALID = 2
284 : };
285 :
286 : #ifndef CCL_LLT
287 : #define ANONYMOUS_NAMESPACE_BEGIN namespace {
288 : #define ANONYMOUS_NAMESPACE_END }
289 : #else
290 : #define ANONYMOUS_NAMESPACE_BEGIN
291 : #define ANONYMOUS_NAMESPACE_END
292 : #endif
293 :
294 : #endif
|