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 "p2p_mgmt.h"
12 :
13 : #include <chrono>
14 : #include <thread>
15 : #include "adapter_error_manager.h"
16 : #include "externalinput_pub.h"
17 : #include "device_capacity.h"
18 : #include "mem_name_repository_pub.h"
19 : #include "sal_pub.h"
20 : #include "driver/ascend_hal.h"
21 : #include "workflow_pub.h"
22 :
23 : namespace hccl {
24 : const u32 DEVICE_PER_MODULE = 8; // A+X 一个mesh卡数
25 : const u32 DIE_PER_MODULE = 16; // 910_93 16die
26 : std::atomic<bool> P2PMgmt::initFlag_ = {false};
27 551 : P2PMgmt &P2PMgmt::Instance()
28 : {
29 551 : static P2PMgmt mgmt;
30 552 : return mgmt;
31 : }
32 :
33 9 : P2PMgmt::P2PMgmt() : deviceType_(DevType::DEV_TYPE_COUNT)
34 : {
35 9 : initFlag_ = true;
36 9 : }
37 :
38 9 : P2PMgmt::~P2PMgmt()
39 : {
40 9 : initFlag_ = false;
41 9 : }
42 :
43 160 : HcclResult P2PMgmt::EnableP2P(std::vector<uint32_t> remoteDevices)
44 : {
45 160 : if (initFlag_) {
46 162 : isStandardCardFor910B_ = IsStandardCardFor910B(remoteDevices);
47 961 : for (auto &remoteDevicePhysicID : remoteDevices) {
48 801 : if (IsNeedEstablishP2Pconnection(remoteDevicePhysicID)) {
49 798 : CHK_RET(EnableP2P(remoteDevicePhysicID));
50 : }
51 : }
52 : }
53 162 : return HCCL_SUCCESS;
54 : }
55 :
56 796 : HcclResult P2PMgmt::EnableP2P(uint32_t remoteDevicePhysicID)
57 : {
58 796 : if (Is310PDevice()) {
59 0 : return HCCL_SUCCESS;
60 : }
61 : int32_t localDeviceLogicID;
62 797 : CHK_RET(hrtGetDevice(&localDeviceLogicID));
63 : u32 maxDeviceNum;
64 801 : CHK_RET(GetMaxDevNum(maxDeviceNum));
65 801 : CHK_PRT_RET(static_cast<u32>(localDeviceLogicID) >= maxDeviceNum,
66 : HCCL_ERROR("[EnableP2P]localDeviceLogicID[%d] is bigger than maxDeviceNum[%u]",
67 : localDeviceLogicID, maxDeviceNum), HCCL_E_INTERNAL);
68 :
69 801 : std::unique_lock<std::mutex> lock(connectionsLock_[localDeviceLogicID]);
70 801 : auto &iterLocalDevice = connectionsInfo_[localDeviceLogicID];
71 801 : auto iterRemoteDevice = iterLocalDevice.find(remoteDevicePhysicID);
72 799 : if ((iterRemoteDevice == iterLocalDevice.end()) || (iterRemoteDevice->second.reference == 0)) {
73 797 : bool isMarsterIdDiff = false;
74 797 : u32 localDevicePhysicID = 0;
75 797 : CHK_RET(hrtGetDevicePhyIdByIndex(localDeviceLogicID, localDevicePhysicID));
76 799 : CHK_RET(CheckMarsterId(remoteDevicePhysicID, localDevicePhysicID, isMarsterIdDiff));
77 799 : HCCL_INFO("[EnableP2P][CheckMarsterId]localDevicePhysicID[%u], remoteDevicePhysicID[%u], isMarsterIdDiff[%s]",
78 : localDevicePhysicID, remoteDevicePhysicID, isMarsterIdDiff ? "true" : "false");
79 799 : if (isMarsterIdDiff) {
80 0 : CHK_RET(hrtEnableP2P(localDeviceLogicID, remoteDevicePhysicID));
81 0 : HCCL_INFO("[EnableP2P]enable p2p: local logic id:%d, local physic id:%u, remote physic id:%u.",
82 : localDeviceLogicID, localDevicePhysicID, remoteDevicePhysicID);
83 : }
84 799 : iterLocalDevice[remoteDevicePhysicID].status = P2PStatus::P2P_STATUS_ENABLING;
85 792 : iterLocalDevice[remoteDevicePhysicID].reference++;
86 795 : return HCCL_SUCCESS;
87 : } else {
88 : // 使已执行过 enable,且未执行过 disable,不重复执行 enable p2p。
89 1 : iterLocalDevice[remoteDevicePhysicID].reference++;
90 : }
91 2 : return HCCL_SUCCESS;
92 797 : }
93 :
94 0 : HcclResult P2PMgmt::DisableAllP2P()
95 : {
96 : int32_t localDeviceLogicID;
97 0 : CHK_RET(hrtGetDevice(&localDeviceLogicID));
98 : u32 maxDeviceNum;
99 0 : CHK_RET(GetMaxDevNum(maxDeviceNum));
100 0 : CHK_PRT_RET(static_cast<u32>(localDeviceLogicID) >= maxDeviceNum,
101 : HCCL_ERROR("[DisableAllP2P]localDeviceLogicID[%d] is bigger than maxDeviceNum[%u]",
102 : localDeviceLogicID, maxDeviceNum), HCCL_E_INTERNAL);
103 :
104 0 : std::map<uint32_t, P2PConnectionInfo> localP2PInfo;
105 0 : std::unique_lock<std::mutex> lock(connectionsLock_[localDeviceLogicID]);
106 0 : auto &iterLocalDevice = connectionsInfo_[localDeviceLogicID];
107 0 : if (iterLocalDevice.empty()) {
108 0 : return HCCL_SUCCESS;
109 : } else {
110 0 : localP2PInfo = iterLocalDevice;
111 : }
112 0 : lock.unlock();
113 :
114 0 : for (auto &iterRemoteDevice : localP2PInfo) {
115 0 : if (iterRemoteDevice.second.reference == 0) {
116 0 : continue;
117 : }
118 :
119 0 : bool isMarsterIdDiff = false;
120 0 : u32 localDevicePhysicID = 0;
121 0 : CHK_RET(hrtGetDevicePhyIdByIndex(localDeviceLogicID, localDevicePhysicID));
122 0 : HcclResult ret = CheckMarsterId(iterRemoteDevice.first, localDevicePhysicID, isMarsterIdDiff);
123 0 : CHK_PRT_RET(ret != HCCL_SUCCESS,
124 : HCCL_ERROR("[Disable][AllP2P]check pcie connection failed. device info: local logic id:%d, "\
125 : "remote physic id:%u.", localDeviceLogicID, iterRemoteDevice.first), ret);
126 0 : if (isMarsterIdDiff) {
127 0 : HCCL_INFO("there is active p2p connections. in P2PMgmt disable all p2p, it is forced to disable p2p. "
128 : "device info: local logic id:%d, remote physic id:%u.", localDeviceLogicID, iterRemoteDevice.first);
129 0 : CHK_RET(hrtDisableP2P(localDeviceLogicID, iterRemoteDevice.first));
130 : }
131 : }
132 :
133 0 : lock.lock();
134 0 : connectionsInfo_[localDeviceLogicID].clear();
135 0 : lock.unlock();
136 0 : return HCCL_SUCCESS;
137 0 : }
138 :
139 310 : HcclResult P2PMgmt::DisableP2P(std::vector<uint32_t> remoteDevices)
140 : {
141 310 : if (initFlag_) {
142 311 : if (Is310PDevice()) {
143 0 : return HCCL_SUCCESS;
144 : }
145 : int32_t localDeviceLogicID;
146 311 : CHK_RET(hrtGetDevice(&localDeviceLogicID));
147 : u32 maxDeviceNum;
148 311 : CHK_RET(GetMaxDevNum(maxDeviceNum));
149 311 : CHK_PRT_RET(static_cast<u32>(localDeviceLogicID) >= maxDeviceNum,
150 : HCCL_ERROR("[DisableP2P]localDeviceLogicID[%d] is bigger than maxDeviceNum[%u]",
151 : localDeviceLogicID, maxDeviceNum), HCCL_E_INTERNAL);
152 :
153 311 : HcclWorkflowMode mode = GetWorkflowMode();
154 311 : if (mode == HcclWorkflowMode::HCCL_WORKFLOW_MODE_OPS_KERNEL_INFO_LIB) {
155 92 : MemNameRepository::GetInstance(localDeviceLogicID)->ClearMemNameRepository();
156 : }
157 :
158 1280 : for (auto &remoteDevicePhysicID : remoteDevices) {
159 969 : if (IsNeedEstablishP2Pconnection(remoteDevicePhysicID)) {
160 969 : CHK_RET(DisableP2P(localDeviceLogicID, remoteDevicePhysicID));
161 : }
162 : }
163 : }
164 311 : return HCCL_SUCCESS;
165 : }
166 :
167 969 : HcclResult P2PMgmt::DisableP2P(uint32_t localDeviceLogicID, uint32_t remoteDevicePhysicID)
168 : {
169 969 : std::unique_lock<std::mutex> lock(connectionsLock_[localDeviceLogicID]);
170 969 : auto &iterLocalDevice = connectionsInfo_[localDeviceLogicID];
171 968 : auto iterRemoteDevice = iterLocalDevice.find(remoteDevicePhysicID);
172 966 : if ((iterRemoteDevice == iterLocalDevice.end()) || (iterRemoteDevice->second.reference == 0)) {
173 168 : HCCL_WARNING("there is no p2p connections, no need to disable p2p. "\
174 : "device info: local logic id:%d, remote physic id:%u.", localDeviceLogicID, remoteDevicePhysicID);
175 168 : return HCCL_SUCCESS;
176 : }
177 :
178 799 : iterRemoteDevice->second.reference--;
179 799 : if (iterRemoteDevice->second.reference == 0) {
180 797 : bool isMarsterIdDiff = false;
181 797 : u32 localDevicePhysicID = 0;
182 797 : CHK_RET(hrtGetDevicePhyIdByIndex(localDeviceLogicID, localDevicePhysicID, true));
183 796 : HCCL_INFO("local logic id:%d, local physic id:%u.", localDeviceLogicID, localDevicePhysicID);
184 798 : HcclResult ret = CheckMarsterId(remoteDevicePhysicID, localDevicePhysicID, isMarsterIdDiff);
185 799 : CHK_PRT_RET(ret != HCCL_SUCCESS,
186 : HCCL_ERROR("[Disable][P2P]check pcie connection failed. device info: local logic id:%d, "\
187 : "remote physic id:%u.", localDeviceLogicID, remoteDevicePhysicID), ret);
188 799 : if (isMarsterIdDiff) {
189 0 : HCCL_INFO("disable p2p: local logic id:%d, remote physic id:%u.", localDeviceLogicID,
190 : remoteDevicePhysicID);
191 0 : CHK_RET(hrtDisableP2P(localDeviceLogicID, remoteDevicePhysicID));
192 : }
193 799 : iterLocalDevice[remoteDevicePhysicID].status = P2PStatus::P2P_STATUS_DISABLED;
194 : }
195 :
196 801 : return HCCL_SUCCESS;
197 969 : }
198 :
199 79 : HcclResult P2PMgmt::WaitP2PEnabled(std::vector<uint32_t> remoteDevices, std::function<bool()> needStop)
200 : {
201 79 : if (initFlag_) {
202 172 : for (auto &remoteDevicePhysicID : remoteDevices) {
203 93 : if (IsNeedEstablishP2Pconnection(remoteDevicePhysicID)) {
204 93 : CHK_RET(WaitP2PEnabled(remoteDevicePhysicID, needStop));
205 : }
206 : }
207 : }
208 79 : return HCCL_SUCCESS;
209 : }
210 :
211 1690 : HcclResult P2PMgmt::CheckMarsterId(
212 : uint32_t remoteDevicePhysicID,
213 : uint32_t localDevicePhysicID,
214 : bool &isMarsterIdDiff)
215 : {
216 1690 : if (localDevicePhysicID == remoteDevicePhysicID) {
217 316 : isMarsterIdDiff = false;
218 316 : return HCCL_SUCCESS;
219 : }
220 1374 : if (deviceType_ == DevType::DEV_TYPE_910B || deviceType_ == DevType::DEV_TYPE_910_93) {
221 : s64 localDevicePhysicValue, remoteDevicePhysicValue;
222 1019 : CHK_RET(hrtGetPhyDeviceInfo(localDevicePhysicID, MODULE_TYPE_SYSTEM, RT_PHY_INFO_TYPE_MASTER_ID,
223 : localDevicePhysicValue));
224 1020 : CHK_RET(hrtGetPhyDeviceInfo(remoteDevicePhysicID, MODULE_TYPE_SYSTEM, RT_PHY_INFO_TYPE_MASTER_ID,
225 : remoteDevicePhysicValue));
226 :
227 1020 : isMarsterIdDiff = (localDevicePhysicValue == remoteDevicePhysicValue) ? false : true;
228 1020 : return HCCL_SUCCESS;
229 : }
230 : LinkTypeInServer linkType;
231 355 : CHK_RET(hrtGetPairDeviceLinkType(localDevicePhysicID, remoteDevicePhysicID, linkType));
232 :
233 710 : isMarsterIdDiff = ((linkType != LinkTypeInServer::HCCS_TYPE) &&
234 355 : (linkType != LinkTypeInServer::SIO_TYPE) && (linkType != LinkTypeInServer::HCCS_SW_TYPE)) ? true : false;
235 355 : return HCCL_SUCCESS;
236 : }
237 :
238 93 : HcclResult P2PMgmt::WaitP2PEnabled(uint32_t remoteDevicePhysicID, std::function<bool()> needStop)
239 : {
240 93 : if (Is310PDevice()) {
241 0 : return HCCL_SUCCESS;
242 : }
243 : int32_t localDeviceLogicID;
244 93 : CHK_RET(hrtGetDevice(&localDeviceLogicID));
245 : u32 maxDeviceNum;
246 93 : CHK_RET(GetMaxDevNum(maxDeviceNum));
247 93 : CHK_PRT_RET(static_cast<u32>(localDeviceLogicID) >= maxDeviceNum,
248 : HCCL_ERROR("[WaitP2PEnabled]localDeviceLogicID[%d] is bigger than maxDeviceNum[%u]",
249 : localDeviceLogicID, maxDeviceNum), HCCL_E_INTERNAL);
250 93 : std::unique_lock<std::mutex> lock(connectionsLock_[localDeviceLogicID]);
251 :
252 93 : auto &iterLocalDevice = connectionsInfo_[localDeviceLogicID];
253 93 : auto iterRemoteDevice = iterLocalDevice.find(remoteDevicePhysicID);
254 186 : bool bErr = (iterRemoteDevice == iterLocalDevice.end()) || (iterRemoteDevice->second.reference == 0) ||
255 93 : (iterRemoteDevice->second.status == P2PStatus::P2P_STATUS_DISABLED);
256 93 : CHK_PRT_RET(bErr, HCCL_ERROR("[Wait][P2PEnabled]wait p2p enabled failed. enable operation has not been executed, "\
257 : "ret[%u]. device info: local logic id:%d, remote physic id:%u.", HCCL_E_INTERNAL, localDeviceLogicID,
258 : remoteDevicePhysicID), HCCL_E_INTERNAL);
259 :
260 93 : if (iterRemoteDevice->second.status == P2PStatus::P2P_STATUS_ENABLED) {
261 0 : return HCCL_SUCCESS;
262 : } else {
263 93 : bool isMarsterIdDiff = false;
264 93 : u32 localDevicePhysicID = 0;
265 93 : CHK_RET(hrtGetDevicePhyIdByIndex(localDeviceLogicID, localDevicePhysicID));
266 93 : HcclResult ret = CheckMarsterId(remoteDevicePhysicID, localDevicePhysicID, isMarsterIdDiff);
267 93 : HCCL_INFO("[WaitP2PEnabled][CheckMarsterId]localDevicePhysicID[%u], remoteDevicePhysicID[%u], isMarsterIdDiff[%s]",
268 : localDevicePhysicID, remoteDevicePhysicID, isMarsterIdDiff ? "true" : "false");
269 93 : CHK_PRT_RET(ret != HCCL_SUCCESS,
270 : HCCL_ERROR("[Wait][P2PEnabled]check pcie connection failed. device info: local logic id:%d, "\
271 : "remote physic id:%u.", localDeviceLogicID, remoteDevicePhysicID), ret);
272 93 : if (isMarsterIdDiff) {
273 0 : CHK_RET(WaitP2PConnected(localDeviceLogicID, remoteDevicePhysicID, needStop));
274 0 : HCCL_INFO("[Wait]enable p2p: local logic id:%d, local physic id:%u, remote physic id:%u.",
275 : localDeviceLogicID, localDevicePhysicID, remoteDevicePhysicID);
276 : }
277 93 : iterLocalDevice[remoteDevicePhysicID].status = P2PStatus::P2P_STATUS_ENABLED;
278 : }
279 93 : return HCCL_SUCCESS;
280 93 : }
281 :
282 0 : HcclResult P2PMgmt::WaitP2PConnected(int32_t localDeviceLogicID, uint32_t remoteDevicePhysicID, std::function<bool()> needStop)
283 : {
284 : // 读取P2P状态超时时间
285 0 : const std::chrono::seconds timeout(GetExternalInputHcclLinkTimeOut());
286 0 : const std::chrono::milliseconds checkP2PTimeInterval(1); // 轮询P2P状态时间 1ms
287 0 : const auto start = TIME_NOW();
288 :
289 : while (true) {
290 0 : CHK_PRT_RET(needStop(), HCCL_ERROR("Terminating operation due to external request"), HCCL_E_INTERNAL);
291 :
292 0 : bool enabled = false;
293 0 : CHK_RET(CheckP2P(remoteDevicePhysicID, enabled));
294 :
295 0 : if (enabled) {
296 0 : HCCL_INFO("connected p2p success, take time [%lld]us. device info: local logic id:%d, remote physic id:%u.",
297 : DURATION_US(TIME_NOW() - start), localDeviceLogicID, remoteDevicePhysicID);
298 0 : return HCCL_SUCCESS;
299 : }
300 0 : std::this_thread::sleep_for(checkP2PTimeInterval);
301 : /* 获取当前时间,如果耗时超过timeout,则返回错误 */
302 : const auto elapsed =
303 0 : std::chrono::duration_cast<std::chrono::seconds>(TIME_NOW() - start);
304 0 : if (elapsed > timeout) {
305 0 : RPT_INNER_ERR_PRT("connected p2p timeout, timeout:%d s.local logicDevid:%d,"\
306 : "remote physic id:%u The possible causes are as follows:1.the connection "\
307 : "between this device and the target device is abnormal 2.an exception occurred "\
308 : "at the target devices 3.The ranktable is not matched.",\
309 : GetExternalInputHcclLinkTimeOut(),
310 : localDeviceLogicID, remoteDevicePhysicID);
311 :
312 0 : HCCL_ERROR("[Wait][P2PConnected]connected p2p timeout, timeout:%d s. local logicDevid:%d, "\
313 : "remote physic id:%u.", GetExternalInputHcclLinkTimeOut(),
314 : localDeviceLogicID, remoteDevicePhysicID);
315 0 : return HCCL_E_DRV;
316 : }
317 0 : }
318 : return HCCL_SUCCESS;
319 : }
320 :
321 0 : HcclResult P2PMgmt::CheckP2P(uint32_t remoteDevicePhysicID, bool &enabled)
322 : {
323 0 : uint32_t status = DRV_P2P_STATUS_DISABLE;
324 : int32_t localDeviceLogicID;
325 0 : CHK_RET(hrtGetDevice(&localDeviceLogicID));
326 :
327 0 : CHK_RET(hrtGetP2PStatus(localDeviceLogicID, remoteDevicePhysicID, &status));
328 :
329 0 : enabled = (status == DRV_P2P_STATUS_ENABLE);
330 0 : return HCCL_SUCCESS;
331 : }
332 :
333 : /*
334 : * ****************************************************************************
335 : * 判断localdevice和remotedevice是否在相同平面,在相同平面内的device间需要做P2P
336 : * *****************************************************************************
337 : */
338 1860 : bool P2PMgmt::IsNeedEstablishP2Pconnection(uint32_t remoteDevicePhysicID)
339 : {
340 1860 : if (static_cast<s32>(remoteDevicePhysicID) == HOST_DEVICE_ID) return false;
341 :
342 : int32_t localDeviceLogicID;
343 1860 : CHK_RET(hrtGetDevice(&localDeviceLogicID));
344 1863 : u32 localDevicePhysicID = 0;
345 1863 : CHK_RET(hrtGetDevicePhyIdByIndex(localDeviceLogicID, localDevicePhysicID));
346 1861 : CHK_RET(hrtGetDeviceType(deviceType_));
347 1857 : if (deviceType_ == DevType::DEV_TYPE_310P3 || isStandardCardFor910B_) {
348 0 : return true;
349 : }
350 1858 : u32 deviceNum = (deviceType_ == DevType::DEV_TYPE_910_93) ? DIE_PER_MODULE : DEVICE_PER_MODULE;
351 3244 : return ((localDevicePhysicID % deviceNum == remoteDevicePhysicID % deviceNum) ||
352 3244 : (localDevicePhysicID / deviceNum == remoteDevicePhysicID / deviceNum));
353 : }
354 :
355 160 : bool P2PMgmt::IsStandardCardFor910B(std::vector<uint32_t>& remoteDevicePhysicIDs)
356 : {
357 : // 非910B场景返回false
358 160 : CHK_RET(hrtGetDeviceType(deviceType_));
359 162 : if (deviceType_ != DevType::DEV_TYPE_910B) {
360 44 : return false;
361 : }
362 :
363 : int32_t localDeviceLogicID;
364 118 : CHK_RET(hrtGetDevice(&localDeviceLogicID));
365 117 : u32 localDevicePhysicID = 0;
366 117 : CHK_RET(hrtGetDevicePhyIdByIndex(localDeviceLogicID, localDevicePhysicID));
367 : LinkTypeInServer linkType;
368 118 : for (auto remoteDevicePhysicID : remoteDevicePhysicIDs){
369 236 : CHK_RET(hrtGetPairDeviceLinkType(localDevicePhysicID, remoteDevicePhysicID, linkType));
370 : // 两卡之间的链路是HCCS或者SIO时,返回false
371 118 : if (linkType == LinkTypeInServer::HCCS_TYPE
372 0 : || linkType == LinkTypeInServer::SIO_TYPE
373 0 : || linkType == LinkTypeInServer::HCCS_SW_TYPE) {
374 118 : return false;
375 : }
376 : }
377 0 : HCCL_INFO("[IsStandardCardFor910B] isStandardCardFor910B_[true]");
378 0 : return true;
379 : }
380 : }
|