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