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 : #include <unordered_set>
12 : #include <mutex>
13 : #include "log.h"
14 : #include "adapter_rts.h"
15 : #include "adapter_hccp.h"
16 : #include "dtype_common.h"
17 : #include "externalinput.h"
18 : #include "network_manager_pub.h"
19 : #include "adapter_hal.h"
20 : #include "dlhal_function.h"
21 : #include "device_capacity.h"
22 :
23 :
24 : constexpr u32 INLINEREDUCE_ALIGN_BYTES_910A = 128;
25 : constexpr u32 INLINEREDUCE_ALIGN_BYTES_310P = 2;
26 : constexpr u32 INLINEREDUCE_ALIGN_BYTES_910_93 = 1; // A2和A3场景的inline reduce不受地址对齐限制
27 : constexpr float BANDWIDTH_HCCS_910A = 10.0f;
28 : constexpr float BANDWIDTH_HCCS_910B = 18.3f;
29 : constexpr float BANDWIDTH_RDMA_910A = 12.5f * 0.8;
30 : constexpr float BANDWIDTH_RDMA_910B = 25.0f * 0.8;
31 : constexpr float BANDWIDTH_HBM_910_93 = 650.0f * 0.9;
32 : constexpr float BANDWIDTH_SIO_910_93 = 240.0f * 0.85;
33 :
34 : // 常用带宽值 GB/s
35 : constexpr float BANDWIDTH_PCIE_GEN3 = 16.0f * 0.85;
36 : constexpr float BANDWIDTH_PCIE_GEN4 = 32.0f * 0.85;
37 : constexpr float BANDWIDTH_PCIE_GEN5 = 64.0f * 0.85;
38 :
39 : // 非超节点模式的server id配置, 通过hrtGetDeviceInfo接口查询到的server id统一为0x3FF
40 : constexpr s64 INVALID_SUPERPOD_SERVERID = 0x3FF;
41 :
42 : namespace hccl {
43 : #ifdef ASCEND_310P_DEVICE
44 : bool g_is310PDevice = true;
45 : #else
46 : bool g_is310PDevice = false;
47 : #endif
48 :
49 1 : bool IsSupportAIVCopy(HcclDataType dataType)
50 : {
51 1 : return (dataType == HCCL_DATA_TYPE_FP16 || dataType == HCCL_DATA_TYPE_INT16 || dataType == HCCL_DATA_TYPE_UINT16 ||
52 0 : dataType == HCCL_DATA_TYPE_FP32 || dataType == HCCL_DATA_TYPE_INT32 || dataType == HCCL_DATA_TYPE_UINT32 ||
53 0 : dataType == HCCL_DATA_TYPE_INT8 || dataType == HCCL_DATA_TYPE_UINT8 || dataType == HCCL_DATA_TYPE_BFP16 ||
54 2 : dataType == HCCL_DATA_TYPE_INT64 || dataType == HCCL_DATA_TYPE_UINT64 || dataType == HCCL_DATA_TYPE_FP64);
55 : }
56 :
57 0 : bool IsSupportAIVReduce(HcclDataType dataType, HcclReduceOp op)
58 : {
59 0 : bool checkDataType =
60 0 : (dataType == HCCL_DATA_TYPE_FP32 || dataType == HCCL_DATA_TYPE_FP16 || dataType == HCCL_DATA_TYPE_INT8 ||
61 0 : dataType == HCCL_DATA_TYPE_INT16 || dataType == HCCL_DATA_TYPE_INT32 || dataType == HCCL_DATA_TYPE_BFP16);
62 0 : bool checkReduceType = (op == HCCL_REDUCE_SUM || op == HCCL_REDUCE_MAX || op == HCCL_REDUCE_MIN);
63 :
64 0 : return checkDataType && checkReduceType;
65 : }
66 :
67 333 : bool IsAddressAlign(const void *inputPtr, const void *outputPtr, DevType devType)
68 : {
69 333 : switch (devType) {
70 183 : case DevType::DEV_TYPE_910:
71 183 : return (reinterpret_cast<intptr_t>(inputPtr) % INLINEREDUCE_ALIGN_BYTES_910A) ==
72 183 : (reinterpret_cast<intptr_t>(outputPtr) % INLINEREDUCE_ALIGN_BYTES_910A);
73 150 : case DevType::DEV_TYPE_910B:
74 : case DevType::DEV_TYPE_910_93:
75 : return (reinterpret_cast<intptr_t>(inputPtr) % INLINEREDUCE_ALIGN_BYTES_910_93) ==
76 150 : (reinterpret_cast<intptr_t>(outputPtr) % INLINEREDUCE_ALIGN_BYTES_910_93);
77 0 : case DevType::DEV_TYPE_310P3:
78 : case DevType::DEV_TYPE_310P1:
79 0 : return (reinterpret_cast<intptr_t>(inputPtr) % INLINEREDUCE_ALIGN_BYTES_310P) ==
80 0 : (reinterpret_cast<intptr_t>(outputPtr) % INLINEREDUCE_ALIGN_BYTES_310P);
81 0 : default:
82 0 : HCCL_WARNING("device type[%d] is out of range", static_cast<s32>(devType));
83 0 : return false;
84 : }
85 : }
86 :
87 319 : bool IsDataTypeSupport(HcclDataType dataType, DevType devType)
88 : {
89 319 : switch (devType) {
90 147 : case DevType::DEV_TYPE_910B:
91 : case DevType::DEV_TYPE_910_93:
92 49 : return (dataType == HCCL_DATA_TYPE_FP32 || dataType == HCCL_DATA_TYPE_FP16 ||
93 0 : dataType == HCCL_DATA_TYPE_INT8 || dataType == HCCL_DATA_TYPE_INT16 ||
94 196 : dataType == HCCL_DATA_TYPE_INT32 || dataType == HCCL_DATA_TYPE_BFP16);
95 172 : case DevType::DEV_TYPE_910:
96 : case DevType::DEV_TYPE_310P1:
97 172 : return dataType == HCCL_DATA_TYPE_FP32;
98 0 : case DevType::DEV_TYPE_310P3:
99 0 : return (dataType == HCCL_DATA_TYPE_FP32 || dataType == HCCL_DATA_TYPE_INT16 ||
100 0 : dataType == HCCL_DATA_TYPE_FP16);
101 0 : default:
102 0 : HCCL_WARNING("device type[%d] is out of range", static_cast<s32>(devType));
103 0 : return false;
104 : }
105 : }
106 :
107 306 : bool IsRedOpSupport(HcclReduceOp op, DevType devType)
108 : {
109 306 : switch (devType) {
110 149 : case DevType::DEV_TYPE_910B:
111 : case DevType::DEV_TYPE_910_93:
112 149 : return (op == HCCL_REDUCE_SUM || op == HCCL_REDUCE_MAX || op == HCCL_REDUCE_MIN);
113 158 : case DevType::DEV_TYPE_910:
114 : case DevType::DEV_TYPE_310P3:
115 : case DevType::DEV_TYPE_310P1:
116 158 : return op == HCCL_REDUCE_SUM;
117 0 : default:
118 0 : HCCL_WARNING("device type[%d] is out of range", static_cast<s32>(devType));
119 0 : return false;
120 : }
121 : }
122 :
123 334 : bool IsSupportSDMAReduce(const void *inputPtr, const void *outputPtr, HcclDataType dataType, HcclReduceOp op)
124 : {
125 : DevType devType;
126 334 : CHK_RET(hrtGetDeviceType(devType));
127 638 : return IsAddressAlign(inputPtr, outputPtr, devType) && IsDataTypeSupport(dataType, devType) &&
128 636 : IsRedOpSupport(op, devType);
129 : }
130 :
131 178 : bool IsSupportRDMAReduce(HcclDataType dataType, HcclReduceOp op)
132 : {
133 178 : bool checkDataType =
134 19 : (dataType == HCCL_DATA_TYPE_FP32 || dataType == HCCL_DATA_TYPE_FP16 || dataType == HCCL_DATA_TYPE_INT8 ||
135 197 : dataType == HCCL_DATA_TYPE_INT16 || dataType == HCCL_DATA_TYPE_INT32 || dataType == HCCL_DATA_TYPE_BFP16);
136 178 : bool checkReduceType = (op == HCCL_REDUCE_SUM || op == HCCL_REDUCE_MAX || op == HCCL_REDUCE_MIN);
137 178 : bool isInfNanMode = IsOverFlowInfNanMode();
138 175 : return checkDataType && checkReduceType && isInfNanMode;
139 : }
140 :
141 0 : HcclResult GetBandWidthPerNPU(u32 level, u32 userRankSize, u32 deviceNumPerAggregation, float &bandWidth)
142 : {
143 : DevType devType;
144 0 : CHK_RET(hrtGetDeviceType(devType));
145 : // 处理 level=1、910B 的特殊条件
146 0 : if (level == 1 && (devType == DevType::DEV_TYPE_910B || devType == DevType::DEV_TYPE_910_93) &&
147 0 : userRankSize == deviceNumPerAggregation * 2) // 2: 910B 16p形态 单server场景
148 : {
149 0 : bandWidth = BANDWIDTH_PCIE_GEN5;
150 0 : return HCCL_SUCCESS;
151 : }
152 : // 其余情况查表
153 : static const std::map<std::pair<u32, DevType>, float> bwTable = {
154 : // level 0
155 : {{0, DevType::DEV_TYPE_310P3}, BANDWIDTH_PCIE_GEN3},
156 : {{0, DevType::DEV_TYPE_910}, BANDWIDTH_HCCS_910A},
157 : {{0, DevType::DEV_TYPE_910B}, BANDWIDTH_HCCS_910B},
158 : {{0, DevType::DEV_TYPE_910_93},BANDWIDTH_HCCS_910B},
159 : // level 1
160 : {{1, DevType::DEV_TYPE_910}, BANDWIDTH_RDMA_910A},
161 : {{1, DevType::DEV_TYPE_910B}, BANDWIDTH_RDMA_910B},
162 : {{1, DevType::DEV_TYPE_910_93},BANDWIDTH_RDMA_910B},
163 : // level 2
164 : {{2, DevType::DEV_TYPE_910_93},BANDWIDTH_HBM_910_93},
165 : // level 3
166 : {{3, DevType::DEV_TYPE_910_93},BANDWIDTH_SIO_910_93},
167 0 : };
168 0 : auto key = std::make_pair(level, devType);
169 0 : auto it = bwTable.find(key);
170 0 : if (it != bwTable.end()) {
171 0 : bandWidth = it->second;
172 0 : return HCCL_SUCCESS;
173 : }
174 0 : HCCL_ERROR("[Get][BandWidthPerNPU] Failed, deviceType[%d] Bandwidth Level[%u]", devType, level);
175 0 : return HCCL_E_NOT_SUPPORT;
176 : }
177 :
178 520 : HcclResult CheckDeviceType(const DevType deviceType)
179 : {
180 520 : if ((deviceType >= DevType::DEV_TYPE_COUNT) || (deviceType < DevType::DEV_TYPE_910)) {
181 0 : HCCL_ERROR("[Check][DeviceType]errNo[0x%016llx] device Type[%d] out of range[%d, %d]",
182 : HCCL_ERROR_CODE(HCCL_E_PARA), deviceType, DevType::DEV_TYPE_910, DevType::DEV_TYPE_NOSOC);
183 0 : return HCCL_E_PARA;
184 : }
185 :
186 520 : return HCCL_SUCCESS;
187 : }
188 :
189 178 : bool IsOverFlowInfNanMode()
190 : {
191 178 : aclrtFloatOverflowMode floatOverflowMode = ACL_RT_OVERFLOW_MODE_UNDEF;
192 178 : HcclResult ret = hrtGetDeviceSatMode(&floatOverflowMode);
193 178 : if (ret != HCCL_SUCCESS) {
194 0 : HCCL_WARNING("[impl][IsOverFlowInfNanMode] GetDeviceSatMode failed");
195 : }
196 354 : return (!GetExternalInputHcclDumpDebug()) && (floatOverflowMode == ACL_RT_OVERFLOW_MODE_INFNAN);
197 : }
198 :
199 84726 : bool Is310PDevice()
200 : {
201 84726 : return g_is310PDevice;
202 : }
203 :
204 0 : bool IsUseSdidForDeviceId(const u32 superDeviceId)
205 : {
206 : DevType devType;
207 0 : CHK_RET(hrtGetDeviceType(devType));
208 0 : if (devType == DevType::DEV_TYPE_910_93 && superDeviceId != INVALID_UINT) {
209 0 : return true;
210 : }
211 0 : return false;
212 : }
213 :
214 3 : HcclResult IsSuperPodMode(bool &useSuperPodMode)
215 : {
216 3 : useSuperPodMode = false;
217 : DevType devType;
218 3 : CHK_RET(hrtGetDeviceType(devType));
219 3 : s64 serverId = INVALID_SUPERPOD_SERVERID;
220 3 : if (devType == DevType::DEV_TYPE_910_93) {
221 : s32 deviceLogicId;
222 2 : HcclResult ret = hrtGetDevice(&deviceLogicId);
223 2 : CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("[IsSuperPodMode]Get device id fail"), ret);
224 2 : CHK_RET(hrtGetDeviceInfo(deviceLogicId, HcclRtDeviceModuleType::HCCL_RT_MODULE_TYPE_SYSTEM,
225 : HcclRtDeviceInfoType::HCCL_INFO_TYPE_SERVER_ID, serverId));
226 2 : useSuperPodMode = (serverId != INVALID_SUPERPOD_SERVERID);
227 2 : if (!useSuperPodMode) {
228 0 : HCCL_WARNING("If server Id is not configured, the network port may need to be " \
229 : "kept up to ensure normal service running, server id[%016llx]", serverId);
230 : }
231 : }
232 3 : HCCL_INFO("[IsSuperPodMode]ret[%d], devType[%d], serverId[%016llx]", useSuperPodMode, devType, serverId);
233 3 : return HCCL_SUCCESS;
234 : }
235 :
236 3448 : HcclResult GetMaxDevNum(u32& MaxDevNum)
237 : {
238 : // 静态缓存最大设备数
239 : static u32 cachedMaxDevNum;
240 : static std::once_flag initFlag; // 用于确保初始化只执行一次
241 : static std::mutex initMutex; // 用于保护call_once调用
242 :
243 : // 使用mutex保护call_once调用
244 3448 : std::lock_guard<std::mutex> lock(initMutex);
245 :
246 : // 使用call_once确保初始化逻辑只执行一次
247 3450 : std::call_once(initFlag, [&]() {
248 : DevType devType;
249 13 : HcclResult result = hrtGetDeviceType(devType);
250 13 : if (result != HCCL_SUCCESS) {
251 0 : HCCL_ERROR("[GetMaxDevNum] [hrtGetDeviceType] get device type failed");
252 : }
253 13 : switch (devType) {
254 0 : case DevType::DEV_TYPE_310P3:
255 0 : cachedMaxDevNum = MAX_DEVICE_NUM_THIRTY_TWO;
256 0 : break;
257 0 : case DevType::DEV_TYPE_950:
258 : case DevType::DEV_TYPE_960:
259 0 : cachedMaxDevNum = MAX_DEVICE_NUM_SIXTY_FIVE;
260 0 : break;
261 13 : default:
262 13 : cachedMaxDevNum = MAX_DEVICE_NUM_SIXTEEN;
263 13 : break;
264 : }
265 13 : });
266 :
267 : // 直接读取缓存值
268 3450 : MaxDevNum = cachedMaxDevNum;
269 3450 : HCCL_DEBUG("[GetMaxDevNum] MaxDevNum[%u]", MaxDevNum);
270 3450 : return HCCL_SUCCESS;
271 3450 : }
272 :
273 : #ifndef OPEN_HCCL_TEST
274 0 : HcclResult IsSupportAicpuNormalQP(const u32& devicePhyId, bool &isSupportNormalQP)
275 : {
276 0 : u32 aiQpCreateVersion = 0;
277 0 : HcclResult ret = hrtRaGetInterfaceVersion(devicePhyId, AI_QP_CREATE, &aiQpCreateVersion);
278 0 : CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("[IsSupportAicpuNormalQP] ret[%d]"
279 : "devicePhyId[%u] not support" , ret, devicePhyId), HCCL_E_NETWORK);
280 0 : if (aiQpCreateVersion >= AI_NORMAL_QP_CREATE_VERSION) {
281 0 : isSupportNormalQP = true;
282 : } else {
283 0 : isSupportNormalQP = false;
284 : }
285 0 : HCCL_DEBUG("IsSupportAicpuNormalQP devicePhyId[%u], isSupportNormalQP[%d].", devicePhyId, isSupportNormalQP);
286 0 : return HCCL_SUCCESS;
287 : }
288 : #endif
289 :
290 : #ifndef OPEN_HCCL_TEST
291 5 : HcclResult IsSupportAIVNormalQP(const u32& devicePhyId, bool &isSupport)
292 : {
293 5 : u32 version = 0;
294 5 : HcclResult ret = hrtRaGetInterfaceVersion(devicePhyId, AI_QP_CREATE_WITH_ATTRS, &version);
295 5 : CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("[hrtRaGetInterfaceVersion] ret[%d]"
296 : "devicePhyId[%u] not support" , ret, devicePhyId), HCCL_E_NETWORK);
297 :
298 5 : if (version >= AI_QP_CREATE_WITH_ATTRS_VERSION) {
299 5 : isSupport = true;
300 : } else {
301 0 : isSupport = false;
302 : }
303 5 : HCCL_INFO("IsSupportAIVNormalQP devicePhyId[%u], isSupport[%d].", devicePhyId, isSupport);
304 5 : return HCCL_SUCCESS;
305 : }
306 : #endif
307 :
308 : #ifndef OPEN_HCCL_TEST
309 153 : bool IsSupportRDMALite(const s32 deviceLogicId)
310 : {
311 153 : return NetworkManager::GetInstance(deviceLogicId).GetRdmaLiteStatus();
312 : }
313 153 : HcclResult IsSupportHccsAndSio(bool &flag)
314 : {
315 153 : flag = false;
316 153 : size_t outputLen = 0;
317 153 : supportFeaturePara inputPara = { 0 };
318 153 : supportFeaturePara outputPara = { 0 };
319 153 : s32 deviceId = 0;
320 153 : CHK_RET(hrtGetDevice(&deviceId));
321 154 : s32 logicDevId = 0;
322 : // 调用驱动接口前需将userDevId转换为logicDevId
323 154 : CHK_RET(hrtGetLogicDevIdByUserDevId(deviceId, logicDevId));
324 153 : inputPara.support_feature = CTRL_SUPPORT_SHMEM_MAP_EXBUS_MASK;
325 153 : inputPara.devid = static_cast<unsigned int>(logicDevId);
326 153 : CHK_RET(hrtHalMemCtl(CTRL_TYPE_SUPPORT_FEATURE, &inputPara, sizeof(supportFeaturePara), &outputPara, &outputLen));
327 :
328 153 : if ((outputPara.support_feature & CTRL_SUPPORT_SHMEM_MAP_EXBUS_MASK) != 0) {
329 0 : flag = true;
330 : }
331 153 : HCCL_INFO("[IsSupportHccsAndSio] isSupportHccsAndSio %d", flag);
332 154 : return HCCL_SUCCESS;
333 : }
334 : #endif
335 :
336 : #ifndef OPEN_HCCL_TEST
337 0 : HcclResult GetMemBlockNum(const u32 devicePhyId, u32& memBlockNum)
338 : {
339 : #ifndef CCL_KERNEL_AICPU
340 0 : u32 info = 0;
341 0 : CHK_RET(DlHalFunction::GetInstance().DlHalFunctionInit());
342 0 : CHK_RET(hrtDrvGetPlatformInfo(&info));
343 0 : if (info == 0) { // 在device侧
344 0 : std::string chipName;
345 0 : if (hrtHalGetChipInfo(devicePhyId, chipName) == HCCL_SUCCESS) {
346 0 : if (chipName.find(SOC_NAME_910B) != std::string::npos) {
347 : // 共享内存池目前不支持动态扩容;910B场景需要的内存池较大,但是申请太大,会导致310P上内存不足,通过硬件区分。
348 0 : memBlockNum = MEM_BLOCK_NUM_BIGER;
349 : }
350 : }
351 0 : }
352 : #endif
353 0 : return HCCL_SUCCESS;
354 : }
355 : #endif
356 : // 获取算子最大超时时间
357 0 : u32 GetNotifyMaxWaitTime()
358 : {
359 : static bool init = false;
360 : static uint32_t notifyMaxWaitTime = NOTIFY_MAX_WAIT_TIME;
361 0 : if (UNLIKELY(!init)) {
362 : DevType deviceType;
363 0 : if (hrtGetDeviceType(deviceType) == HCCL_SUCCESS) {
364 0 : notifyMaxWaitTime = (deviceType == DevType::DEV_TYPE_910_93 || deviceType == DevType::DEV_TYPE_910B) ?\
365 : NOTIFY_MAX_WAIT_TIME_910_93 : NOTIFY_MAX_WAIT_TIME;
366 0 : init = true;
367 : }
368 : }
369 :
370 0 : HCCL_INFO("[GetNotifyMaxWaitTime] notifyMaxWaitTime is %us", notifyMaxWaitTime);
371 0 : return notifyMaxWaitTime;
372 : }
373 :
374 2 : HcclResult IsSupportAtomicWrite(DevType deviceType, u32 devicePhyId, bool& isSupportAtomicWrite)
375 : {
376 2 : if (deviceType == DevType::DEV_TYPE_910_93 || deviceType == DevType::DEV_TYPE_910B) {
377 0 : u32 version = 0;
378 0 : HcclResult ret = hrtRaGetInterfaceVersion(devicePhyId, RA_RS_GET_ROCE_API, &version);
379 0 : CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("%s call hrtRaGetInterfaceVersion ret[%d] devicePhyId[%u]",
380 : __func__, ret, devicePhyId), HCCL_E_NETWORK);
381 0 : isSupportAtomicWrite = (version >= RA_RS_ATOMIC_WRITE_VERSION);
382 0 : HCCL_INFO("%s deviceType[%d] devicePhyId[%u], version[%u], isSupportAtomicWrite[%d]",
383 : __func__, deviceType, devicePhyId, version, isSupportAtomicWrite);
384 0 : } else {
385 2 : isSupportAtomicWrite = false;
386 2 : HCCL_INFO("%s deviceType[%d] not support", __func__, deviceType);
387 : }
388 2 : return HCCL_SUCCESS;
389 : }
390 : }
|