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 "heartbeat.h"
12 : #include <set>
13 : #include <tuple>
14 : #include "device_capacity.h"
15 : #include "externalinput_pub.h"
16 : #include "env_config.h"
17 : #include "opexecounter_pub.h"
18 : #include "hccl_communicator.h"
19 : #include "task_exception_handler_pub.h"
20 : #include "comm_configer.h"
21 : #include "snapshot_control.h"
22 :
23 : namespace hccl {
24 1645 : Heartbeat& Heartbeat::GetInstance(s32 deviceLogicID)
25 : {
26 2490 : static Heartbeat hb[MAX_MODULE_DEVICE_NUM];
27 1645 : if (static_cast<u32>(deviceLogicID) >= MAX_MODULE_DEVICE_NUM) {
28 527 : HCCL_WARNING("[Heartbeat][%s]deviceLogicID[%d] is invalid", __func__, deviceLogicID);
29 527 : return hb[0];
30 : }
31 1118 : return hb[deviceLogicID];
32 : }
33 :
34 845 : Heartbeat::~Heartbeat()
35 : {
36 845 : if (!groupMap_.empty()) {
37 1 : HCCL_RUN_INFO("[Heartbeat]groupMap_ size[%llu].", groupMap_.size());
38 2 : for (auto iter = groupMap_.begin(); iter != groupMap_.end(); iter++) {
39 1 : HCCL_RUN_WARNING("[Heartbeat]UnRegister group[%s].", iter->first.c_str());
40 : }
41 : }
42 845 : (void)DeInit();
43 845 : groupMap_.clear();
44 845 : retryEnableTable_.clear();
45 845 : backupEnableTable_.clear();
46 845 : opInfoIndexMap_.clear();
47 845 : opInfoQueue_.clear();
48 845 : opInfoMap_.clear();
49 845 : recvOpInfoList_.clear();
50 845 : inconsistentOpMap_.clear();
51 845 : srTagMap_.clear();
52 845 : }
53 :
54 25 : bool Heartbeat::IsEnableBackupLink()
55 : {
56 25 : std::lock_guard<std::mutex> lock(backupEnableMutex_);
57 : // 若backupEnableTable_不为空,则当前还有通信域使能借轨,需要获取备用的cqe
58 25 : auto isEmpty = backupEnableTable_.empty();
59 25 : return !isEmpty;
60 25 : }
61 :
62 5 : HcclResult Heartbeat::InitNic(
63 : const NicType nicType, const s32 devicePhyId, const s32 deviceLogicId, const hccl::HcclIpAddress ip, const u32 port,
64 : const bool isBackUp)
65 : {
66 : HcclNetDevCtx nicCtx;
67 5 : CHK_RET(HcclNetOpenDev(&nicCtx, nicType, devicePhyId, deviceLogicId, ip));
68 5 : CHK_PTR_NULL(nicCtx);
69 5 : netDevCtxMap_.insert(std::make_pair(ip, nicCtx));
70 :
71 5 : if (!isBackUp) {
72 5 : std::shared_ptr<HcclSocket> tempSocket;
73 5 : EXCEPTION_CATCH((tempSocket = std::make_shared<HcclSocket>(nicCtx, port)), return HCCL_E_PTR);
74 5 : CHK_RET(tempSocket->Init());
75 5 : CHK_RET(tempSocket->Listen());
76 :
77 0 : listenSocketMap_.insert(std::make_pair(ip, tempSocket));
78 5 : }
79 :
80 0 : HCCL_INFO(
81 : "[Heartbeat][%s]NicType[%d], devicePhyId[%d], deviceLogicId[%d], ip[%s], port[%u], isBackUp[%d].", __func__,
82 : nicType, devicePhyId, deviceLogicId, ip.GetReadableAddress(), port, isBackUp);
83 0 : return HCCL_SUCCESS;
84 : }
85 :
86 5 : HcclResult Heartbeat::InitDeviceNic(const RankInfo& locRank, bool isNeedNic, u32 port)
87 : {
88 5 : if (isNeedNic && locRank.nicIp.size() != 0) {
89 0 : nicIp_ = locRank.nicIp[0];
90 0 : u32 nicPort = (port == HCCL_INVALID_PORT) ? locRank.deviceNicPort : port;
91 0 : if (locRank.nicDeploy == NICDeployment::NIC_DEPLOYMENT_DEVICE && !nicIp_.IsInvalid()
92 0 : && netDevCtxMap_.find(nicIp_) == netDevCtxMap_.end()) {
93 0 : CHK_RET(InitNic(NicType::DEVICE_NIC_TYPE, devicePhyId_, deviceLogicId_, nicIp_, nicPort));
94 : }
95 : }
96 :
97 5 : if (isNeedNic && locRank.backupNicIp.size() != 0 && IsEnableBackupLink()) {
98 0 : backupNicIp_ = locRank.backupNicIp[0];
99 0 : u32 backupPort = HCCL_INVALID_PORT; // 不初始化备用网卡上的Socket
100 0 : if (locRank.nicDeploy == NICDeployment::NIC_DEPLOYMENT_DEVICE
101 0 : && netDevCtxMap_.find(backupNicIp_) == netDevCtxMap_.end()) {
102 0 : CHK_RET(InitNic(
103 : NicType::DEVICE_NIC_TYPE, deviceBackUpPhyId_, deviceBackupLogicId_, backupNicIp_, backupPort, true));
104 : }
105 : }
106 5 : return HCCL_SUCCESS;
107 : }
108 :
109 5 : HcclResult Heartbeat::InitHostNic(const RankInfo& locRank, bool isNeedNic, u32 port)
110 : {
111 5 : if (!isNeedNic || locRank.nicDeploy != NICDeployment::NIC_DEPLOYMENT_HOST) {
112 5 : return HCCL_SUCCESS;
113 : }
114 :
115 0 : if (!locRank.nicIp[0].IsInvalid()) {
116 0 : u32 nicPort = (port == HCCL_INVALID_PORT) ? locRank.deviceNicPort : port;
117 0 : nicIp_ = locRank.nicIp[0];
118 0 : if (netDevCtxMap_.find(nicIp_) == netDevCtxMap_.end()) {
119 0 : CHK_RET(InitNic(NicType::HOST_NIC_TYPE, devicePhyId_, deviceLogicId_, nicIp_, nicPort));
120 : }
121 : } else {
122 0 : if (netDevCtxMap_.find(locRank.hostIp) == netDevCtxMap_.end()) {
123 0 : u32 hostPort = GetHostPort(devicePhyId_);
124 0 : CHK_RET(InitNic(NicType::HOST_NIC_TYPE, devicePhyId_, deviceLogicId_, locRank.hostIp, hostPort));
125 : }
126 : }
127 0 : return HCCL_SUCCESS;
128 : }
129 :
130 5 : HcclResult Heartbeat::Init(
131 : const RankInfo& locRank, [[maybe_unused]] const bool useSuperPodMode, const bool isNeedNic, const u32 port,
132 : const std::string& group)
133 : {
134 5 : HCCL_INFO("[%s] heartbeat Init begin.", __func__);
135 5 : devicePhyId_ = locRank.devicePhyId;
136 5 : if (IsEnableBackupLink()) {
137 2 : CHK_RET(hrtGetPairDevicePhyId(devicePhyId_, deviceBackUpPhyId_));
138 : }
139 5 : superDeviceId_ = locRank.superDeviceId;
140 5 : if (devicePhyId_ == static_cast<u32>(HOST_DEVICE_ID)) {
141 1 : deviceLogicId_ = devicePhyId_;
142 1 : deviceBackupLogicId_ = deviceBackUpPhyId_;
143 : } else {
144 4 : CHK_RET(hrtGetDeviceIndexByPhyId(devicePhyId_, deviceLogicId_));
145 4 : if (IsEnableBackupLink()) {
146 1 : CHK_RET(hrtGetDeviceIndexByPhyId(deviceBackUpPhyId_, deviceBackupLogicId_));
147 : }
148 : }
149 5 : std::unique_lock<std::mutex> mapLock(ctxMapMutex_);
150 5 : CHK_RET(InitDeviceNic(locRank, isNeedNic, port));
151 5 : CHK_RET(InitHostNic(locRank, isNeedNic, port));
152 5 : mapLock.unlock();
153 5 : uid_ = GetUId(locRank);
154 5 : nicDeploy_ = locRank.nicDeploy;
155 5 : s32 hcclExecTimeOut = CommConfiger::GetInstance().GetCommConfigExecTimeOut(group);
156 5 : stuckDetectTime_ = std::max(hcclExecTimeOut / HCCL_STUCK_DETECT_TIME_BASE, HCCL_STUCK_DETECT_TIME_MIN);
157 5 : startSendRecvTask_ = true;
158 5 : sendRecvThread_.reset(new (std::nothrow) std::thread(&Heartbeat::HeartbeatStatusMonitor, std::ref(*this)));
159 5 : CHK_SMART_PTR_NULL(sendRecvThread_);
160 5 : lostThreshold_ = HCCL_LOST_THRESHOLD; // 心跳丢失阈值为30s
161 5 : initialized_ = true;
162 5 : isPaused_ = false;
163 5 : isDeInit_ = false;
164 5 : HCCL_INFO("[%s] heartbeat Init end, stuckDetectTime[%d s].", __func__, stuckDetectTime_);
165 5 : return HCCL_SUCCESS;
166 5 : }
167 :
168 850 : HcclResult Heartbeat::DeInit()
169 : {
170 850 : HCCL_INFO("[%s] heartbeat deinit begin.", __func__);
171 850 : isDeInit_ = true;
172 850 : startSendRecvTask_ = false;
173 850 : linkThreadRunning_ = false;
174 850 : isPaused_ = false;
175 850 : if (sendRecvThread_) {
176 6 : if (sendRecvThread_->joinable()) {
177 5 : sendRecvThread_->join();
178 : }
179 : }
180 : {
181 850 : std::unique_lock<std::mutex> lock(ProcessLock_);
182 850 : for (auto iter = rankId2SocketMap_.begin(); iter != rankId2SocketMap_.end(); iter++) {
183 0 : if (iter->second.socket->GetLocalRole() == HcclSocketRole::SOCKET_ROLE_SERVER) {
184 0 : CHK_PRT_RET(
185 : listenSocketMap_.find(iter->second.socket->GetLocalIp()) == listenSocketMap_.end(),
186 : HCCL_ERROR(
187 : "ip[%s] listenSocketMap is not found", iter->second.socket->GetLocalIp().GetReadableAddress()),
188 : HCCL_E_NOT_FOUND);
189 0 : listenSocketMap_[iter->second.socket->GetLocalIp()]->DelWhiteList(iter->second.wlistInfosVec);
190 : }
191 0 : iter->second.socket->Close();
192 : }
193 850 : rankId2SocketMap_.clear();
194 850 : rankId2StatusMap_.clear();
195 850 : }
196 850 : std::queue<HeartBeatFrame> empty;
197 850 : std::swap(errStatusQueue_, empty);
198 :
199 850 : std::unique_lock<std::mutex> mapLock(ctxMapMutex_);
200 850 : listenSocketMap_.clear();
201 855 : for (auto& iter : netDevCtxMap_) {
202 5 : HcclNetCloseDev(iter.second);
203 : }
204 850 : vnicIp_.clear();
205 850 : nicIp_.clear();
206 850 : backupNicIp_.clear();
207 :
208 850 : netDevCtxMap_.clear();
209 850 : mapLock.unlock();
210 :
211 850 : initialized_ = false;
212 850 : HCCL_INFO("[%s] heartbeat deinit end.", __func__);
213 850 : return HCCL_SUCCESS;
214 850 : }
215 :
216 0 : HcclResult Heartbeat::PrepareConnect(ConnInfo& info)
217 : {
218 0 : CHK_SMART_PTR_NULL(info.socket);
219 0 : if (info.socket->GetLocalRole() == HcclSocketRole::SOCKET_ROLE_SERVER) {
220 0 : CHK_PRT_RET(
221 : listenSocketMap_.find(info.socket->GetLocalIp()) == listenSocketMap_.end(),
222 : HCCL_ERROR("ip[%s] listenSocketMap is not found", info.socket->GetLocalIp().GetReadableAddress()),
223 : HCCL_E_NOT_FOUND);
224 0 : CHK_RET(listenSocketMap_[info.socket->GetLocalIp()]->AddWhiteList(info.wlistInfosVec));
225 : } else {
226 0 : if (info.socket->GetStatus() != HcclSocketStatus::SOCKET_OK) {
227 0 : CHK_RET(info.socket->Connect());
228 : }
229 : }
230 :
231 0 : return HCCL_SUCCESS;
232 : }
233 :
234 28 : HcclResult Heartbeat::RegisterRanks(
235 : [[maybe_unused]] DevType devType, const RankInfo& locRank, std::vector<RankInfo>& rankInfos, const u32 port,
236 : const bool isNeedNic, const std::string& group, bool useSuperPodMode, bool isUsedRdma)
237 : {
238 28 : HCCL_INFO(
239 : "[%s] group[%s] isUsedRdma[%d], isNeedNic[%d], RegisterRanks Start.", __func__, group.c_str(), isUsedRdma,
240 : isNeedNic);
241 : // 线程锁,防止多线程同时Init
242 28 : std::unique_lock<std::mutex> lock(ProcessLock_);
243 28 : auto iter = groupMap_.find(group);
244 28 : if (iter != groupMap_.end()) {
245 18 : HCCL_INFO("group[%s] has Registered, skip.", group.c_str());
246 18 : return HCCL_SUCCESS;
247 : }
248 :
249 10 : if (!initialized_) {
250 6 : CHK_RET(Init(locRank, useSuperPodMode, isNeedNic, port, group));
251 : }
252 :
253 : // 刷新uid_,防止不同通信域下serverId不一致问题
254 10 : uid_ = GetUId(locRank);
255 10 : lock.unlock();
256 :
257 10 : std::unique_lock<std::mutex> mapLock(ctxMapMutex_);
258 10 : if (devicePhyId_ != static_cast<u32>(HOST_DEVICE_ID) && rankInfos.size() > 1 && vnicIp_.IsInvalid()) {
259 6 : vnicIp_ = HcclIpAddress(useSuperPodMode ? superDeviceId_ : devicePhyId_);
260 6 : u32 vnicPort = (port == HCCL_INVALID_PORT) ? locRank.deviceVnicPort : port;
261 6 : CHK_RET(hrtRaGetSingleSocketVnicIpInfo(
262 : devicePhyId_, (useSuperPodMode ? DeviceIdType::DEVICE_ID_TYPE_SDID : DeviceIdType::DEVICE_ID_TYPE_PHY_ID),
263 : (useSuperPodMode ? superDeviceId_ : devicePhyId_), vnicIp_));
264 6 : if (netDevCtxMap_.find(vnicIp_) == netDevCtxMap_.end()) {
265 5 : CHK_RET(InitNic(NicType::VNIC_TYPE, devicePhyId_, deviceLogicId_, vnicIp_, vnicPort));
266 : }
267 : }
268 :
269 : // 防止首次没有读到nicIp, 后续注册心跳的时候刷新上
270 5 : if (isNeedNic && nicIp_.IsInvalid() && locRank.nicIp.size() != 0) {
271 0 : nicIp_ = locRank.nicIp[0];
272 0 : u32 nicPort = (port == HCCL_INVALID_PORT) ? locRank.deviceNicPort : port;
273 0 : if (locRank.nicDeploy == NICDeployment::NIC_DEPLOYMENT_DEVICE && !nicIp_.IsInvalid()
274 0 : && netDevCtxMap_.find(nicIp_) == netDevCtxMap_.end()) {
275 0 : CHK_RET(InitNic(NicType::DEVICE_NIC_TYPE, devicePhyId_, deviceLogicId_, nicIp_, nicPort));
276 : }
277 : }
278 :
279 5 : if (isNeedNic && backupNicIp_.IsInvalid() && locRank.backupNicIp.size() != 0) {
280 0 : backupNicIp_ = locRank.backupNicIp[0];
281 0 : u32 backupPort = HCCL_INVALID_PORT; // 不初始化备用网卡上的Socket
282 0 : if (IsEnableBackupLink()) {
283 0 : CHK_RET(hrtGetPairDevicePhyId(devicePhyId_, deviceBackUpPhyId_));
284 0 : CHK_RET(hrtGetDeviceIndexByPhyId(deviceBackUpPhyId_, deviceBackupLogicId_));
285 0 : if (locRank.nicDeploy == NICDeployment::NIC_DEPLOYMENT_DEVICE
286 0 : && netDevCtxMap_.find(backupNicIp_) == netDevCtxMap_.end()) {
287 0 : CHK_RET(InitNic(
288 : NicType::DEVICE_NIC_TYPE, deviceBackUpPhyId_, deviceBackupLogicId_, backupNicIp_, backupPort,
289 : true));
290 : }
291 : }
292 : }
293 :
294 5 : u32 tcpPort = 0;
295 5 : if (isNeedNic && locRank.nicDeploy == NICDeployment::NIC_DEPLOYMENT_HOST) {
296 0 : if (!locRank.nicIp[0].IsInvalid()) {
297 0 : nicIp_ = locRank.nicIp[0];
298 0 : tcpPort = (port == HCCL_INVALID_PORT) ? locRank.deviceNicPort : port;
299 0 : if (netDevCtxMap_.find(nicIp_) == netDevCtxMap_.end()) {
300 0 : CHK_RET(InitNic(NicType::HOST_NIC_TYPE, devicePhyId_, deviceLogicId_, nicIp_, tcpPort));
301 : }
302 : } else {
303 0 : if (netDevCtxMap_.find(locRank.hostIp) == netDevCtxMap_.end()) {
304 0 : tcpPort = GetHostPort(devicePhyId_);
305 0 : CHK_RET(InitNic(NicType::HOST_NIC_TYPE, devicePhyId_, deviceLogicId_, locRank.hostIp, tcpPort));
306 : }
307 : }
308 : }
309 5 : mapLock.unlock();
310 :
311 5 : lock.lock();
312 61 : for (const auto& remRank : rankInfos) {
313 56 : UIDType rem = GetUId(remRank);
314 56 : rankId2StatusMap_.insert(rem, Status());
315 56 : groupMap_[group].insert(std::make_pair(rem, NO_CONN));
316 56 : HCCL_INFO("[%s]group[%s] remote:%s", __func__, group.c_str(), FormatUId(rem).c_str());
317 : }
318 5 : lock.unlock();
319 :
320 5 : if (!GetExternalInputHcclHeartBeatEnable()) {
321 0 : HCCL_RUN_INFO(
322 : "[Heartbeat][%s] Enable HcclHeartBeatLink is [%d]. It's unnecessary to "
323 : "register Ranks. Group[%s] isUsedRdma[%d], netDevCtxMap size[%llu]",
324 : __func__, GetExternalInputHcclHeartBeatEnable(), group.c_str(), isUsedRdma, netDevCtxMap_.size());
325 0 : return HCCL_SUCCESS;
326 : }
327 :
328 5 : std::map<UIDType, ConnInfo> needConnectRank;
329 5 : CHK_RET(GetConnectRank(locRank, rankInfos, needConnectRank, useSuperPodMode, isUsedRdma));
330 :
331 5 : std::unique_lock<std::mutex> linkInfolock(hbLinkConnInfoMtx_);
332 13 : for (auto& item : needConnectRank) {
333 8 : if (item.second.newConn == true) {
334 6 : hbLinkConnInfo_[group].push(std::move(item));
335 : }
336 : }
337 5 : linkInfolock.unlock();
338 :
339 5 : lock.lock();
340 13 : for (auto& item : needConnectRank) {
341 8 : if (item.second.newConn == true) {
342 6 : rankId2LinkStatusMap_[item.first] = HBLinkStatus::HEARTBEAT_LINK_BUILDING;
343 2 : } else if (
344 2 : groupMap_[group].find(item.first) == groupMap_[group].end()
345 2 : || (groupMap_[group].count(item.first) && groupMap_[group][item.first] == NO_CONN)) {
346 2 : rankId2SocketMap_.ref(item.first);
347 2 : HCCL_RUN_INFO(
348 : "group:[%s], establish rank[%s] to rank[%s] heartbeat connection success.", group.c_str(),
349 : FormatUId(uid_).c_str(), FormatUId(item.first).c_str());
350 2 : groupMap_[group][item.first] = HAS_CONN;
351 : }
352 : }
353 5 : lock.unlock();
354 :
355 5 : HCCL_INFO(
356 : "[%s]group[%s] isUsedRdma[%d], netDevCtxMap size[%llu], RegisterRanks Completed", __func__, group.c_str(),
357 : isUsedRdma, netDevCtxMap_.size());
358 5 : return HCCL_SUCCESS;
359 28 : }
360 :
361 0 : void Heartbeat::CreateLinkWithRemote(std::string group, UIDType rem, ConnInfo needConnectRank)
362 : {
363 : // 给当前线程添加名字
364 0 : const std::string threadName = "hb" + FormatUId(rem);
365 0 : SetThreadName(threadName);
366 :
367 0 : if (deviceLogicId_ != static_cast<u32>(HOST_DEVICE_ID)) {
368 0 : hrtSetDevice(deviceLogicId_);
369 : }
370 0 : HCCL_INFO("[Heartbeat][CreateLinkWithRemote] Group[%s], thread[%s] start...", group.c_str(), threadName.c_str());
371 :
372 0 : HcclResult ret = PrepareConnect(needConnectRank);
373 0 : if (ret != HCCL_SUCCESS) {
374 0 : HCCL_ERROR(
375 : "[CreateLinkWithRemote] PrepareConnect ret[%d], group[%s], remote uid[%s].", ret, group.c_str(),
376 : FormatUId(rem).c_str());
377 0 : if (deviceLogicId_ != static_cast<u32>(HOST_DEVICE_ID)) {
378 0 : hrtResetDevice(deviceLogicId_);
379 : }
380 0 : return;
381 : }
382 0 : auto HEART_CREATE_LINK_TIMEOUT = std::chrono::seconds(GetExternalInputHcclLinkTimeOut());
383 0 : auto startTime = std::chrono::steady_clock::now();
384 0 : while (linkThreadRunning_) {
385 0 : if ((std::chrono::steady_clock::now() - startTime) >= HEART_CREATE_LINK_TIMEOUT) {
386 0 : HCCL_RUN_WARNING(
387 : "establish rank[%s] to rank[%s] heartbeat connection failed. Reason: get rasocket timeout,"
388 : "timeout[%llds], the HCCL_CONNECT_TIMEOUT may be insufficient. Group[%s].",
389 : FormatUId(uid_).c_str(), FormatUId(rem).c_str(), HEART_CREATE_LINK_TIMEOUT, group.c_str());
390 0 : break;
391 : }
392 :
393 0 : if (needConnectRank.socket->GetStatus() == HcclSocketStatus::SOCKET_TIMEOUT
394 0 : || needConnectRank.socket->GetStatus() == HcclSocketStatus::SOCKET_ERROR) {
395 0 : HCCL_RUN_WARNING(
396 : "establish rank[%s] to rank[%s] heartbeat connection failed. Reason: socket status [%d]"
397 : "Group[%s]",
398 : FormatUId(uid_).c_str(), FormatUId(rem).c_str(), needConnectRank.socket->GetStatus(), group.c_str());
399 0 : needConnectRank.socket->Close();
400 0 : break;
401 : }
402 :
403 0 : if (needConnectRank.socket->GetStatus() == HcclSocketStatus::SOCKET_CONNECTING) {
404 0 : SaluSleep(ONE_MILLISECOND_OF_USLEEP);
405 0 : continue;
406 : }
407 :
408 0 : std::unique_lock<std::mutex> lock(ProcessLock_);
409 0 : if (groupMap_.find(group) == groupMap_.end()) {
410 0 : HCCL_RUN_WARNING(
411 : "establish rank[%s] to rank[%s] heartbeat connection failed. Reason: Group[%s] has been"
412 : "Unregistered.",
413 : FormatUId(uid_).c_str(), FormatUId(rem).c_str(), group.c_str());
414 0 : needConnectRank.socket->Close();
415 0 : lock.unlock();
416 0 : break;
417 : }
418 0 : needConnectRank.newConn = false;
419 0 : rankId2SocketMap_.insert(rem, needConnectRank);
420 : // 心跳socket建链完成后,需要立即及激活其心跳收发能力
421 0 : auto frameSize = GetExternalInconsistentCheckSwitch() == InconsistentCheckMode::ON ?
422 : sizeof(HeartBeatFrameWithOpCheck) :
423 0 : sizeof(HeartBeatFrame);
424 0 : if (rankId2SocketMap_[rem].recvBuffer.Init(BASE_NUMBER * frameSize) != HCCL_SUCCESS) { // 2倍帧长,确报不会溢出
425 0 : HCCL_RUN_WARNING(
426 : "establish rank[%s] to rank[%s] heartbeat connection failed. Reason: socket recv buffer init"
427 : "failed. Group[%s].",
428 : FormatUId(uid_).c_str(), FormatUId(rem).c_str(), group.c_str());
429 0 : rankId2SocketMap_.erase(rem);
430 0 : lock.unlock();
431 0 : break;
432 : }
433 0 : rankId2LinkStatusMap_[rem] = HBLinkStatus::HEARTBEAT_LINK_COMPLETED;
434 0 : groupMap_[group][rem] = HAS_CONN;
435 0 : lock.unlock();
436 0 : HCCL_RUN_INFO(
437 : "group:[%s], establish rank[%s] to rank[%s] heartbeat connection success.", group.c_str(),
438 : FormatUId(uid_).c_str(), FormatUId(rem).c_str());
439 0 : break;
440 0 : }
441 0 : if (deviceLogicId_ != static_cast<u32>(HOST_DEVICE_ID)) {
442 0 : hrtResetDevice(deviceLogicId_);
443 : }
444 :
445 0 : HCCL_INFO("[%s] Thread [%s] end...", __func__, threadName.c_str());
446 0 : return;
447 0 : }
448 :
449 20 : void Heartbeat::RegisterRetryInfo(const std::string& commIdentifier, bool retryEnable, bool backupEnable)
450 : {
451 : {
452 20 : std::lock_guard<std::mutex> retryEnablelock(retryEnableMutex_);
453 20 : auto search = retryEnableTable_.find(commIdentifier);
454 20 : if (search != retryEnableTable_.end()) {
455 19 : HCCL_INFO(
456 : "[%s]register identifier[%s] retryEnable[%d] has been registered", __func__, commIdentifier.c_str(),
457 : search->second);
458 : } else {
459 1 : retryEnableTable_.insert({commIdentifier, retryEnable});
460 1 : HCCL_RUN_INFO("[%s]register identifier[%s] retryEnable[%d]", __func__, commIdentifier.c_str(), retryEnable);
461 : }
462 20 : }
463 20 : if (backupEnable) {
464 : // 若当前通信域使能借轨,则加入到backupEnableTable_中
465 0 : std::lock_guard<std::mutex> backupEnablelock(backupEnableMutex_);
466 0 : if (backupEnableTable_.find(commIdentifier) == backupEnableTable_.end()) {
467 0 : backupEnableTable_.insert(commIdentifier);
468 0 : HCCL_RUN_INFO(
469 : "[%s]register identifier[%s] backupEnable[%d]", __func__, commIdentifier.c_str(), backupEnable);
470 : }
471 0 : }
472 20 : return;
473 : }
474 21 : HcclResult Heartbeat::RegisterToHeartBeat(
475 : u32 userRank, DevType devType, std::vector<RankInfo>& rankInfoList, const u32 port, const bool isNeedNic,
476 : const std::string& commIdentifier, bool useSuperPodMode, bool isUsedRdmaLevel0, bool retryEnable, bool backupEnable)
477 : {
478 21 : if (Is310PDevice() || devType == DevType::DEV_TYPE_310P3) {
479 0 : return HCCL_SUCCESS;
480 : }
481 :
482 21 : CHK_PRT_RET(
483 : rankInfoList.size() == 1,
484 : HCCL_WARNING(
485 : "[RegisterToHeartBeat]Identifier[%s] rankSize[%llu] needn't to register.", commIdentifier.c_str(),
486 : rankInfoList.size()),
487 : HCCL_SUCCESS);
488 :
489 20 : RankInfo locRank;
490 20 : for (auto rank : rankInfoList) {
491 20 : if (userRank == rank.userRank) {
492 20 : locRank = rank;
493 20 : break;
494 : }
495 20 : }
496 :
497 20 : RegisterRetryInfo(commIdentifier, retryEnable, backupEnable);
498 :
499 20 : CHK_RET(RegisterRanks(
500 : devType, locRank, rankInfoList, port, isNeedNic, commIdentifier, useSuperPodMode, isUsedRdmaLevel0));
501 19 : return HCCL_SUCCESS;
502 20 : }
503 :
504 0 : HcclResult Heartbeat::RegisterToHeartBeat(
505 : u32 userRank, DevType devType, std::vector<RankInfo>& rankInfoList, const u32 port, const bool isNeedNic,
506 : u32 peerRankId, const std::string& commIdentifier, const std::string& tag, bool useSuperPodMode,
507 : bool isUsedRdmaLevel0, bool retryEnable, bool backupEnable)
508 : {
509 0 : if (Is310PDevice() || devType == DevType::DEV_TYPE_310P3 || (rankInfoList[userRank].devicePhyId == HOST_DEVICE_ID)
510 0 : || (rankInfoList[peerRankId].devicePhyId == HOST_DEVICE_ID)) {
511 0 : return HCCL_SUCCESS;
512 : }
513 :
514 0 : CHK_PRT_RET(
515 : rankInfoList.size() == 1,
516 : HCCL_WARNING(
517 : "[RegisterToHeartBeat]Identifier[%s] rankSize[%llu] needn't to register.", commIdentifier.c_str(),
518 : rankInfoList.size()),
519 : HCCL_SUCCESS);
520 :
521 0 : RankInfo locRank;
522 0 : std::vector<RankInfo> peerRankInfoList;
523 0 : bool findLoc = false;
524 0 : bool findPeer = false;
525 0 : for (auto rank : rankInfoList) {
526 0 : if (userRank == rank.userRank) {
527 0 : locRank = rank;
528 0 : peerRankInfoList.push_back(rank);
529 0 : findLoc = true;
530 : }
531 :
532 0 : if (peerRankId == rank.userRank) {
533 0 : peerRankInfoList.push_back(rank);
534 0 : findPeer = true;
535 : }
536 :
537 0 : if (findLoc && findPeer) {
538 0 : break;
539 : }
540 0 : }
541 0 : RegisterRetryInfo(commIdentifier, retryEnable, backupEnable);
542 0 : CHK_RET(RegisterRanks(devType, locRank, peerRankInfoList, port, isNeedNic, tag, useSuperPodMode, isUsedRdmaLevel0));
543 0 : return HCCL_SUCCESS;
544 0 : }
545 :
546 : HcclResult
547 0 : Heartbeat::AddOpInfoToHeartBeat(const std::string& identifier, const OpInfoDesc& opInfo, const std::string& newTag)
548 : {
549 0 : AddOpInfo(identifier, opInfo, newTag);
550 0 : return HCCL_SUCCESS;
551 : }
552 :
553 645 : HcclResult Heartbeat::DeleteOpInfoToHeartBeat(const std::string& identifier, const std::string& newTag)
554 : {
555 645 : std::string tag;
556 645 : if (newTag != "") {
557 0 : tag = newTag;
558 : } else {
559 645 : tag = identifier;
560 : }
561 645 : CHK_PRT_RET(initialized_ == false, HCCL_WARNING("Heartbeat has been destroyed"), HCCL_SUCCESS);
562 0 : std::unique_lock<std::mutex> lock(opInfoMapMutex_);
563 0 : opInfoMap_.erase(tag);
564 0 : opInfoIndexMap_.erase(tag);
565 0 : return HCCL_SUCCESS;
566 645 : }
567 :
568 216 : HcclResult Heartbeat::UnRegisterRanks(const std::string& group)
569 : {
570 216 : CHK_PRT_RET(initialized_ == false, HCCL_WARNING("Heartbeat has been destroyed"), HCCL_SUCCESS);
571 7 : std::set<UIDType> remInQueue;
572 7 : std::unique_lock<std::mutex> connInfoLock(hbLinkConnInfoMtx_);
573 7 : if (hbLinkConnInfo_.find(group) != hbLinkConnInfo_.end()) {
574 9 : while (!hbLinkConnInfo_[group].empty()) {
575 6 : remInQueue.insert(hbLinkConnInfo_[group].front().first);
576 6 : hbLinkConnInfo_[group].pop();
577 : }
578 : }
579 7 : hbLinkConnInfo_.erase(group);
580 7 : connInfoLock.unlock();
581 :
582 : {
583 7 : std::unique_lock<std::mutex> lock(ProcessLock_);
584 :
585 13 : for (const auto& rem : remInQueue) {
586 6 : if (rankId2LinkStatusMap_[rem] == HBLinkStatus::HEARTBEAT_LINK_BUILDING) {
587 6 : rankId2LinkStatusMap_[rem] = HBLinkStatus::HEARTBEAT_LINK_NOT_START;
588 6 : HCCL_INFO(
589 : "[%s] group[%s] rem[%s] is in hbLinkConnInfo deque. Status change to not start", __func__,
590 : group.c_str(), FormatUId(rem).c_str());
591 : }
592 : }
593 7 : auto iter = groupMap_.find(group);
594 7 : if (iter == groupMap_.end()) {
595 3 : HCCL_INFO("group[%s] hasn't Registered, skip", group.c_str());
596 3 : return HCCL_SUCCESS;
597 : }
598 :
599 40 : for (const auto& remRank : groupMap_[group]) {
600 36 : UIDType rem = remRank.first;
601 36 : rankId2StatusMap_.erase(rem);
602 36 : if (remRank.second == HAS_CONN) {
603 2 : if (rankId2SocketMap_.count(rem) == 1) {
604 0 : if (rankId2SocketMap_[rem].socket->GetLocalRole() == HcclSocketRole::SOCKET_ROLE_SERVER) {
605 0 : CHK_PRT_RET(
606 : listenSocketMap_.find(rankId2SocketMap_[rem].socket->GetLocalIp())
607 : == listenSocketMap_.end(),
608 : HCCL_ERROR(
609 : "ip[%s] listenSocketMap is not found",
610 : rankId2SocketMap_[rem].socket->GetLocalIp().GetReadableAddress()),
611 : HCCL_E_NOT_FOUND);
612 0 : listenSocketMap_[rankId2SocketMap_[rem].socket->GetLocalIp()]->DelWhiteList(
613 0 : rankId2SocketMap_[rem].wlistInfosVec);
614 : }
615 0 : rankId2SocketMap_[rem].socket->Close();
616 0 : rankId2LinkStatusMap_[rem] = HBLinkStatus::HEARTBEAT_LINK_NOT_START;
617 : }
618 2 : HCCL_INFO("[%s]group[%s] socket erase remote:%s", __func__, group.c_str(), FormatUId(rem).c_str());
619 2 : rankId2SocketMap_.erase(rem);
620 : }
621 36 : HCCL_INFO("[%s]group[%s] status erase remote:%s", __func__, group.c_str(), FormatUId(rem).c_str());
622 : }
623 4 : groupMap_.erase(iter);
624 4 : HCCL_INFO("[%s]group[%s] UnregisterRanks Completed.", __func__, group.c_str());
625 7 : }
626 :
627 4 : if (groupMap_.size() == 0) {
628 3 : HCCL_RUN_INFO("[%s]Entry HeartBeat DeInit.", __func__);
629 3 : CHK_RET(DeInit());
630 : }
631 4 : return HCCL_SUCCESS;
632 7 : }
633 :
634 807 : void Heartbeat::UnRegisterToHeartBeat(DevType devType, const std::string& commIdentifier)
635 : {
636 807 : if (Is310PDevice() || devType == DevType::DEV_TYPE_310P3) {
637 4 : return;
638 : }
639 803 : ClearRetryEnableMapItem(commIdentifier);
640 803 : HcclResult ret = UnRegisterRanks(commIdentifier);
641 800 : if (ret != HCCL_SUCCESS) {
642 0 : HCCL_ERROR("UnRegisterToHeartBeat failed");
643 : }
644 : }
645 0 : void Heartbeat::UnRegisterToHeartBeat(DevType devType, const std::string& commIdentifier, const std::string& tag)
646 : {
647 0 : if (Is310PDevice() || devType == DevType::DEV_TYPE_310P3) {
648 0 : return;
649 : }
650 0 : ClearRetryEnableMapItem(commIdentifier);
651 0 : HcclResult ret = UnRegisterRanks(tag);
652 0 : if (ret != HCCL_SUCCESS) {
653 0 : HCCL_ERROR("UnRegisterToHeartBeat failed");
654 : }
655 : }
656 :
657 108 : UIDType Heartbeat::GetUId(const RankInfo& rankInfo) const
658 : {
659 108 : UIDType uid;
660 108 : s32 ret = snprintf_s(
661 : uid.id, sizeof(uid.id), sizeof(uid.id) - 1, "%s%s%s", rankInfo.serverId.c_str(), "/",
662 216 : std::to_string(rankInfo.devicePhyId).c_str());
663 108 : if (ret == -1) {
664 0 : HCCL_WARNING("[Heartbeat][%s] snprintf_s failed", __func__);
665 : }
666 108 : return uid;
667 : }
668 :
669 636 : std::string Heartbeat::FormatUId(const UIDType& uid) const { return uid.id; }
670 :
671 13 : std::string Heartbeat::GetConnTag(HcclSocketRole role, UIDType& rem)
672 : {
673 13 : std::string tag;
674 13 : if (role == HcclSocketRole::SOCKET_ROLE_CLIENT) {
675 7 : tag = "HeartBeat_" + FormatUId(uid_) + "_to_" + FormatUId(rem);
676 : } else {
677 6 : tag = "HeartBeat_" + FormatUId(rem) + "_to_" + FormatUId(uid_);
678 : }
679 :
680 13 : return tag;
681 0 : }
682 :
683 13 : HcclResult Heartbeat::GetConnInfo(
684 : RankInfo& remRank, bool useSuperPodMode, HcclSocketRole role, HcclSocketType type,
685 : std::map<UIDType, ConnInfo>& needConnectRank)
686 : {
687 13 : bool newConn = true;
688 13 : UIDType rem = GetUId(remRank);
689 : {
690 13 : std::unique_lock<std::mutex> lock(ProcessLock_);
691 13 : if (rankId2LinkStatusMap_.find(rem) == rankId2LinkStatusMap_.end()) {
692 8 : rankId2LinkStatusMap_[rem] = HBLinkStatus::HEARTBEAT_LINK_NOT_START;
693 5 : } else if (
694 5 : rankId2LinkStatusMap_[rem] == HBLinkStatus::HEARTBEAT_LINK_BUILDING
695 5 : || rankId2LinkStatusMap_[rem] == HBLinkStatus::HEARTBEAT_LINK_COMPLETED) {
696 2 : newConn = false;
697 : }
698 13 : }
699 13 : std::string tag = GetConnTag(role, rem);
700 13 : HcclIpAddress remNicIp;
701 13 : if (remRank.nicIp.size() > 0) {
702 13 : remNicIp = remRank.nicIp[0];
703 : }
704 :
705 13 : if (type == HcclSocketType::SOCKET_NIC && (nicIp_.IsInvalid() || remNicIp.IsInvalid())) {
706 5 : HCCL_INFO("No Invalid Nic, Skip");
707 5 : return HCCL_SUCCESS;
708 : }
709 :
710 : u32 remoteDeviceId;
711 : u32 localDeviceId;
712 : DeviceIdType deviceIdType;
713 8 : if (useSuperPodMode) {
714 0 : remoteDeviceId = remRank.superDeviceId;
715 0 : localDeviceId = superDeviceId_;
716 0 : deviceIdType = DeviceIdType::DEVICE_ID_TYPE_SDID;
717 : } else {
718 8 : remoteDeviceId = remRank.devicePhyId;
719 8 : localDeviceId = devicePhyId_;
720 8 : deviceIdType = DeviceIdType::DEVICE_ID_TYPE_PHY_ID;
721 : }
722 :
723 8 : HcclIpAddress locNicIp = nicIp_;
724 8 : if (type == HcclSocketType::SOCKET_VNIC) {
725 : // 获取本端vnic ip
726 8 : locNicIp = HcclIpAddress(localDeviceId);
727 8 : CHK_RET(hrtRaGetSingleSocketVnicIpInfo(devicePhyId_, deviceIdType, localDeviceId, locNicIp));
728 : // 获取远端vnic ip
729 8 : remNicIp = HcclIpAddress(remoteDeviceId);
730 8 : CHK_RET(hrtRaGetSingleSocketVnicIpInfo(devicePhyId_, deviceIdType, remoteDeviceId, remNicIp));
731 : }
732 :
733 8 : u32 port = HCCL_INVALID_PORT;
734 8 : if (remRank.nicDeploy == NICDeployment::NIC_DEPLOYMENT_HOST) {
735 0 : port = GetHostPort(remoteDeviceId);
736 : } else {
737 8 : port = GetPort(type, remRank.userRank, remoteDeviceId);
738 : }
739 :
740 8 : HCCL_INFO("remote userRank[%u], connect port[%u].", remRank.userRank, port);
741 :
742 8 : std::shared_ptr<HcclSocket> tempSocket;
743 8 : std::unique_lock<std::mutex> mapLock(ctxMapMutex_);
744 8 : CHK_PRT_RET(
745 : netDevCtxMap_.find(locNicIp) == netDevCtxMap_.end(),
746 : HCCL_ERROR("ip[%s] netDevCtx is not found, socket type[%d]", locNicIp.GetReadableAddress(), type),
747 : HCCL_E_NOT_FOUND);
748 8 : HcclNetDevCtx devCtx = netDevCtxMap_[locNicIp];
749 8 : mapLock.unlock();
750 8 : ConnInfo conn(newConn, tempSocket);
751 8 : if (role == HcclSocketRole::SOCKET_ROLE_SERVER) {
752 : SocketWlistInfo wlistInfo;
753 4 : wlistInfo.connLimit = 1;
754 4 : CHK_SAFETY_FUNC_RET(memcpy_s(&wlistInfo.tag[0], sizeof(wlistInfo.tag), tag.c_str(), tag.size() + 1));
755 :
756 4 : wlistInfo.remoteIp.addr = remNicIp.GetBinaryAddress().addr;
757 4 : wlistInfo.remoteIp.addr6 = remNicIp.GetBinaryAddress().addr6;
758 4 : conn.wlistInfosVec.push_back(wlistInfo);
759 : }
760 :
761 8 : EXCEPTION_CATCH((tempSocket = std::make_shared<HcclSocket>(tag, devCtx, remNicIp, port, role)), return HCCL_E_PTR);
762 8 : CHK_RET(tempSocket->Init());
763 :
764 8 : conn.socket = tempSocket;
765 :
766 8 : needConnectRank.insert(std::make_pair(rem, conn));
767 8 : return HCCL_SUCCESS;
768 13 : }
769 :
770 3 : HcclResult GetSocketTypeIn91093(
771 : const std::vector<RankInfo>& rankInfos, bool useSuperPodMode, u32 index, u32 nextOrPrevIndex, HcclSocketType& type)
772 : {
773 : // 910_93 Type要动态改一下 1. 同server vnic 2. 不同server 超结点内vnic 超结点间nic
774 3 : auto locRank = rankInfos[index];
775 3 : auto rankInfo = rankInfos[nextOrPrevIndex];
776 3 : bool localUseSuporPodModel = useSuperPodMode && locRank.superPodId.empty() == false;
777 3 : bool needSuperModeHb = localUseSuporPodModel && useSuperPodMode && rankInfo.superPodId.empty() == false;
778 3 : if (needSuperModeHb) {
779 0 : bool isInterServer = false;
780 0 : uint32_t userRankServerId = 0;
781 0 : uint32_t remoteRankServerId = 0;
782 0 : rtError_t ret = rtGetServerIDBySDID(locRank.superDeviceId, &userRankServerId);
783 0 : CHK_PRT_RET(
784 : ret != RT_ERROR_NONE,
785 : HCCL_ERROR(
786 : "[GetSocketTypeIn91093]rtGetServerIDBySDID failed sdid[0x%08x], serverID[%u], ret[%u]",
787 : locRank.superDeviceId, userRankServerId, ret),
788 : HCCL_E_RUNTIME);
789 0 : ret = rtGetServerIDBySDID(rankInfo.superDeviceId, &remoteRankServerId);
790 0 : CHK_PRT_RET(
791 : ret != RT_ERROR_NONE,
792 : HCCL_ERROR(
793 : "[GetSocketTypeIn91093]rtGetServerIDBySDID failed sdid[0x%08x], serverID[%u], ret[%u]",
794 : rankInfo.superDeviceId, remoteRankServerId, ret),
795 : HCCL_E_RUNTIME);
796 0 : isInterServer = (userRankServerId != remoteRankServerId) || (locRank.superPodId != rankInfo.superPodId);
797 0 : HCCL_INFO(
798 : "[GetSocketTypeIn91093]localSDID[0x%08x], localdevicePhyId[%d], localServerId[%s], "
799 : "localServerIdBySDID[%d], localSuperPodId[%s], "
800 : "remoteSDID[0x%08x], remotedevicePhyId[%d], remoteServerId[%s], remoteServerIdBySDID[%d], "
801 : "remoteSuperPodId[%s], "
802 : "isInterServer[%s]",
803 : locRank.superDeviceId, locRank.devicePhyId, locRank.serverId.c_str(), userRankServerId,
804 : locRank.superPodId.c_str(), rankInfo.superDeviceId, rankInfo.devicePhyId, rankInfo.serverId.c_str(),
805 : remoteRankServerId, rankInfo.superPodId.c_str(), isInterServer ? "true" : "false");
806 0 : if (!isInterServer) { // serverId相同表示同超结点同server
807 0 : type = HcclSocketType::SOCKET_VNIC;
808 0 : } else if (locRank.superPodId == rankInfo.superPodId) { // 同超结点
809 0 : type = (GetExternalInputInterHccsDisable() == true) ? HcclSocketType::SOCKET_NIC :
810 : HcclSocketType::SOCKET_VNIC;
811 : } else { // 表示不同超结点
812 0 : type = HcclSocketType::SOCKET_NIC;
813 : }
814 : }
815 3 : return HCCL_SUCCESS;
816 3 : }
817 :
818 : template <typename T>
819 10 : HcclResult Heartbeat::GetSamePlaneConnInfo(
820 : HcclSocketType type, std::vector<std::pair<T, u32>>& connVec, T& locId, std::vector<RankInfo>& rankInfos,
821 : std::map<UIDType, ConnInfo>& needConnectRank, bool useSuperPodMode, u32 worldRank)
822 : {
823 10 : u32 index = 0;
824 23 : for (; index < connVec.size(); index++) {
825 23 : if (connVec[index].first == locId) {
826 10 : break;
827 : }
828 : }
829 :
830 : DevType devType;
831 10 : CHK_RET(hrtGetDeviceType(devType));
832 10 : u32 connCount = connVec.size();
833 10 : if (connCount <= 1) {
834 3 : HCCL_INFO("nothing need to connect");
835 7 : } else if (connCount == 2) { // 2个rank, 只需建链一条连接
836 1 : u32 nextIndex = connVec[(index + 1) % connCount].second;
837 1 : if (devType == DevType::DEV_TYPE_910_93) {
838 1 : CHK_RET(GetSocketTypeIn91093(rankInfos, useSuperPodMode, connVec[index].second, nextIndex, type));
839 : }
840 1 : HCCL_INFO(
841 : "[GetSamePlaneConnInfo]local rank[%u], remote rank[%u], type[%d]", worldRank,
842 : rankInfos[nextIndex].worldRank, type);
843 1 : if (index == 0) {
844 1 : CHK_RET(GetConnInfo(
845 : rankInfos[nextIndex], useSuperPodMode, HcclSocketRole::SOCKET_ROLE_CLIENT, type, needConnectRank));
846 : } else {
847 0 : CHK_RET(GetConnInfo(
848 : rankInfos[nextIndex], useSuperPodMode, HcclSocketRole::SOCKET_ROLE_SERVER, type, needConnectRank));
849 : }
850 : } else {
851 6 : u32 nextIndex = connVec[(index + 1) % connCount].second;
852 6 : if (devType == DevType::DEV_TYPE_910_93) {
853 1 : CHK_RET(GetSocketTypeIn91093(rankInfos, useSuperPodMode, connVec[index].second, nextIndex, type));
854 : }
855 6 : HCCL_INFO(
856 : "[GetSamePlaneConnInfo][nextIndex]local rank[%u], remote rank[%u], type[%d]", worldRank,
857 : rankInfos[nextIndex].worldRank, type);
858 6 : CHK_RET(GetConnInfo(
859 : rankInfos[nextIndex], useSuperPodMode, HcclSocketRole::SOCKET_ROLE_CLIENT, type, needConnectRank));
860 :
861 6 : u32 prevIndex = connVec[(index + connCount - 1) % connCount].second;
862 6 : if (devType == DevType::DEV_TYPE_910_93) {
863 1 : CHK_RET(GetSocketTypeIn91093(rankInfos, useSuperPodMode, connVec[index].second, prevIndex, type));
864 : }
865 6 : HCCL_INFO(
866 : "[GetSamePlaneConnInfo][prevIndex]local rank[%u], remote rank[%u], type[%d]", worldRank,
867 : rankInfos[prevIndex].worldRank, type);
868 6 : CHK_RET(GetConnInfo(
869 : rankInfos[prevIndex], useSuperPodMode, HcclSocketRole::SOCKET_ROLE_SERVER, type, needConnectRank));
870 : }
871 :
872 10 : return HCCL_SUCCESS;
873 : }
874 :
875 5 : HcclResult Heartbeat::GetConnectRank(
876 : const RankInfo& locRank, std::vector<RankInfo>& rankInfos, std::map<UIDType, ConnInfo>& needConnectRank,
877 : bool useSuperPodMode, bool isUsedRdma)
878 : {
879 5 : std::vector<std::pair<u32, u32>> devVec;
880 5 : std::vector<std::pair<std::string, u32>> serVec;
881 : DevType devType;
882 5 : CHK_RET(hrtGetDeviceType(devType));
883 :
884 61 : for (u32 index = 0; index < rankInfos.size(); index++) {
885 56 : auto rankInfo = rankInfos[index];
886 56 : if (rankInfo.serverId == locRank.serverId) {
887 45 : devVec.push_back(std::make_pair(rankInfo.devicePhyId, index));
888 : }
889 56 : if (rankInfo.devicePhyId == locRank.devicePhyId) {
890 11 : serVec.push_back(std::make_pair(rankInfo.serverId, index));
891 : }
892 56 : }
893 : // server内单环dev排布, 为兼容310P(devId为0, 2, 4...), 扩展为16
894 : int* ringConfig;
895 5 : int ringConfig910A[16] = {0, 3, 1, 2, 7, 4, 6, 5, 4, 6, 2, 0, 3, 1, 5, 7};
896 5 : int ringConfig910B[16] = {0, 1, 2, 3, 4, 5, 6, 7, 15, 14, 13, 12, 11, 10, 9, 8};
897 :
898 5 : ringConfig = ringConfig910A;
899 5 : if (devType == DevType::DEV_TYPE_910B || devType == DevType::DEV_TYPE_310P3
900 5 : || devType == DevType::DEV_TYPE_910_93) {
901 1 : ringConfig = ringConfig910B;
902 : }
903 5 : std::sort(devVec.begin(), devVec.end(), [&](const std::pair<u32, u32> p1, const std::pair<u32, u32> p2) {
904 167 : return ringConfig[p1.first] < ringConfig[p2.first];
905 : });
906 :
907 5 : std::sort(
908 12 : serVec.begin(), serVec.end(), [](const std::pair<std::string, u32>& p1, const std::pair<std::string, u32>& p2) {
909 12 : return p1.first < p2.first;
910 : });
911 5 : u32 locDevId = locRank.devicePhyId;
912 5 : u32 worldRank = locRank.worldRank;
913 :
914 5 : HcclSocketType devSocketType = ((devType == DevType::DEV_TYPE_910B) && isUsedRdma) ? HcclSocketType::SOCKET_NIC :
915 : HcclSocketType::SOCKET_VNIC;
916 5 : CHK_RET(
917 : GetSamePlaneConnInfo(devSocketType, devVec, locDevId, rankInfos, needConnectRank, useSuperPodMode, worldRank));
918 :
919 5 : auto nodeId = locRank.serverId;
920 5 : CHK_RET(GetSamePlaneConnInfo(
921 : HcclSocketType::SOCKET_NIC, serVec, nodeId, rankInfos, needConnectRank, useSuperPodMode, worldRank));
922 5 : return HCCL_SUCCESS;
923 5 : }
924 :
925 1 : void Heartbeat::AddOpInfo(const std::string& identifier, const OpInfoDesc& opInfo, const std::string& paramTag)
926 : {
927 1 : if (!opInfo.isValid || opInfo.opType == HcclCMDType::HCCL_CMD_BATCH_SEND_RECV) {
928 : // 若当前opInfo为无效值或者为batchsendrecv算子时,无需添加
929 0 : return;
930 : }
931 : // 添加一个opInfo到发送队列中
932 1 : OpInfoDesc opInfoTmp = opInfo;
933 1 : std::string tag;
934 1 : if (opInfo.opType == HcclCMDType::HCCL_CMD_SEND || opInfo.opType == HcclCMDType::HCCL_CMD_RECEIVE) {
935 0 : RegisterSROpIdentifier(identifier, paramTag);
936 0 : tag = paramTag;
937 : } else {
938 1 : tag = identifier;
939 : }
940 1 : std::lock_guard<std::mutex> lock(opInfoQueueMutex_);
941 :
942 1 : auto opInfoIndexIter = opInfoIndexMap_.find(tag);
943 1 : if (opInfoIndexIter == opInfoIndexMap_.end()) {
944 1 : opInfoIndexMap_.insert(std::make_pair(tag, 1));
945 1 : opInfoTmp.index = 1;
946 : } else {
947 0 : opInfoTmp.index = ++(opInfoIndexIter->second);
948 : }
949 1 : opInfoQueue_.push_back(std::make_pair(tag, opInfoTmp));
950 1 : HCCL_DEBUG(
951 : "[Heartbeat][AddOpInfo]opType[%d], dataType[%d], reduce[%d], count[%llu], root[%d], tag[%s], index[%llu] add "
952 : "success",
953 : opInfoTmp.opType, opInfoTmp.dataType, opInfoTmp.reduceOp, opInfoTmp.count, opInfoTmp.root, tag.c_str(),
954 : opInfoTmp.index);
955 :
956 : // 限制发送队列的长度,防止内存逐渐溢出
957 1 : if (opInfoQueue_.size() > OPINFO_QUEUE_MAX_SIZE) {
958 0 : opInfoQueue_.pop_front();
959 : }
960 1 : return;
961 1 : }
962 :
963 2 : void Heartbeat::GetOneOpInfo(std::string& tag, OpInfoDesc& opInfo)
964 : {
965 : // 从发送队列中获取一个opInfo发送给对端
966 2 : std::unique_lock<std::mutex> lock(opInfoQueueMutex_);
967 2 : if (opInfoQueue_.empty()) {
968 : static OpInfoDesc defaultOpInfo;
969 1 : opInfo = defaultOpInfo;
970 1 : return;
971 : }
972 1 : auto opInfoPair = opInfoQueue_.front();
973 1 : opInfoQueue_.pop_front();
974 1 : lock.unlock();
975 :
976 1 : tag = opInfoPair.first;
977 1 : opInfo = opInfoPair.second;
978 1 : std::unique_lock<std::mutex> mapLock(opInfoMapMutex_);
979 1 : if (opInfoMap_.find(tag) == opInfoMap_.end()) {
980 1 : std::map<u64, OpInfoDesc> opInfoList;
981 1 : opInfoList.insert(std::make_pair(opInfo.index, opInfo));
982 1 : opInfoMap_.insert(std::make_pair(tag, opInfoList));
983 1 : } else {
984 0 : opInfoMap_[tag].insert(std::make_pair(opInfo.index, opInfo));
985 : }
986 :
987 : // 限制发送队列的长度,防止内存逐渐溢出
988 1 : while (opInfoMap_[tag].size() > OPINFO_QUEUE_MAX_SIZE) {
989 : // 删除index最小的数据,防止内存不断增加
990 0 : auto smallIt = opInfoMap_[tag].begin();
991 0 : opInfoMap_[tag].erase(smallIt);
992 : }
993 :
994 1 : HCCL_DEBUG(
995 : "[Heartbeat][GetOneOpInfo]opType[%d], dataType[%d], reduce[%d], count[%llu], root[%d], tag[%s], "
996 : "index[%llu] get success",
997 : opInfo.opType, opInfo.dataType, opInfo.reduceOp, opInfo.count, opInfo.root, tag.c_str(), opInfo.index);
998 1 : return;
999 2 : }
1000 :
1001 0 : void Heartbeat::GetSendOpInfoList(OpInfoTagQueueFrame& opInfoTagQueueFrame)
1002 : {
1003 0 : if (GetExternalInconsistentCheckSwitch() != InconsistentCheckMode::ON) {
1004 0 : return;
1005 : }
1006 0 : while (opInfoQueueForSend_.size() < OPINFO_TAG_QUEUE_NUM * OPINFO_SEND_NUM_BY_TAG) {
1007 0 : OpInfoDesc opInfo;
1008 0 : std::string tag;
1009 0 : GetOneOpInfo(tag, opInfo);
1010 0 : if (opInfo.isValid) {
1011 0 : opInfoQueueForSend_.push_back(std::make_pair(tag, opInfo));
1012 : } else {
1013 0 : break;
1014 : }
1015 0 : }
1016 :
1017 0 : HCCL_DEBUG("[%s] opInfoQueueForSend_.size[%d] begin", __func__, opInfoQueueForSend_.size());
1018 0 : auto& opInfoTagQueue = opInfoTagQueueFrame.opInfoTagQueue;
1019 0 : for (auto iter = opInfoQueueForSend_.begin(); iter != opInfoQueueForSend_.end();) {
1020 0 : bool isAdd = false;
1021 0 : for (u32 index = 0; index < OPINFO_TAG_QUEUE_NUM; index++) {
1022 : // 当前 index 对应的 opInfoTagQueue 为未初始化状态
1023 0 : if (strncmp(opInfoTagQueue[index].identifier, "\0", ROOTINFO_INDENTIFIER_MAX_LENGTH) == 0) {
1024 0 : memcpy_s(
1025 0 : opInfoTagQueue[index].identifier, iter->first.size() + 1, iter->first.c_str(),
1026 0 : iter->first.size() + 1);
1027 0 : opInfoTagQueue[index].opInfoList[opInfoTagQueue[index].opInfoNum] = iter->second;
1028 0 : opInfoTagQueue[index].opInfoNum++;
1029 0 : isAdd = true;
1030 0 : HCCL_DEBUG(
1031 : "[%s]opInfoTagQueue[%d] add success identifier[%s] ", __func__, index,
1032 : opInfoTagQueue[index].identifier);
1033 0 : break;
1034 : }
1035 : // 当前 index 对应的 opInfoTagQueue 已经被某个tag 的算子占用
1036 0 : else if (
1037 0 : strncmp(opInfoTagQueue[index].identifier, iter->first.c_str(), ROOTINFO_INDENTIFIER_MAX_LENGTH) == 0) {
1038 0 : if (opInfoTagQueue[index].opInfoNum < OPINFO_SEND_NUM_BY_TAG) {
1039 0 : opInfoTagQueue[index].opInfoList[opInfoTagQueue[index].opInfoNum] = iter->second;
1040 0 : opInfoTagQueue[index].opInfoNum++;
1041 0 : isAdd = true;
1042 0 : HCCL_DEBUG(
1043 : "[%s]opInfoTagQueue[%d] has exists and add success identifier[%s] ", __func__, index,
1044 : opInfoTagQueue[index].identifier);
1045 0 : break;
1046 : }
1047 : }
1048 : }
1049 0 : if (isAdd) {
1050 0 : iter = opInfoQueueForSend_.erase(iter);
1051 : } else {
1052 0 : iter++; // opInfoQueueForSend_ 残留数据会被保存到下一轮 GetSendOpInfoList
1053 : }
1054 : }
1055 0 : return;
1056 : }
1057 :
1058 6 : void Heartbeat::SaveOpInfo(const OpInfoTagQueueFrame& opInfoTagQueueFrame, UIDType& src)
1059 : {
1060 6 : const auto& opInfoTagQueue = opInfoTagQueueFrame.opInfoTagQueue;
1061 66 : for (u32 index = 0; index < OPINFO_TAG_QUEUE_NUM; index++) {
1062 60 : std::string tag = std::string(opInfoTagQueue[index].identifier);
1063 64 : for (u32 num = 0; num < opInfoTagQueue[index].opInfoNum; num++) {
1064 4 : std::unique_lock<std::mutex> lock(opInfoMapMutex_);
1065 : // 保存接收到的opInfo到接收队列中
1066 4 : auto& opInfo = opInfoTagQueue[index].opInfoList[num];
1067 4 : recvOpInfoList_.push_back(std::make_tuple(opInfo, tag, src));
1068 4 : HCCL_DEBUG(
1069 : "[Heartbeat][%s]tag[%s], opType[%d], dataType[%d], reduce[%d], count[%u], root[%d], index[%llu] get "
1070 : "success",
1071 : __func__, tag.c_str(), opInfo.opType, opInfo.dataType, opInfo.reduceOp, opInfo.count, opInfo.root,
1072 : opInfo.index);
1073 4 : }
1074 60 : }
1075 6 : std::unique_lock<std::mutex> lock(opInfoMapMutex_);
1076 6 : while (recvOpInfoList_.size() > OPINFO_QUEUE_MAX_SIZE) { // 可能存在误丢
1077 0 : recvOpInfoList_.pop_front();
1078 : }
1079 :
1080 12 : return;
1081 6 : }
1082 :
1083 : HcclResult
1084 6 : Heartbeat::CheckIsSameOp(const OpInfoDesc& localOpInfo, const OpInfoDesc& remoteOpInfo, InconsistentType& status)
1085 : {
1086 6 : if (localOpInfo.opType == HcclCMDType::HCCL_CMD_SEND) {
1087 2 : if (remoteOpInfo.opType != HcclCMDType::HCCL_CMD_RECEIVE) {
1088 1 : status = InconsistentType::OPTYPE_INCONSISTENT;
1089 1 : return HCCL_SUCCESS;
1090 : }
1091 4 : } else if (localOpInfo.opType == HcclCMDType::HCCL_CMD_RECEIVE) {
1092 1 : if (remoteOpInfo.opType != HcclCMDType::HCCL_CMD_SEND) {
1093 1 : status = InconsistentType::OPTYPE_INCONSISTENT;
1094 1 : return HCCL_SUCCESS;
1095 : }
1096 3 : } else if (localOpInfo.opType != remoteOpInfo.opType) {
1097 1 : status = InconsistentType::OPTYPE_INCONSISTENT;
1098 1 : return HCCL_SUCCESS;
1099 : }
1100 :
1101 3 : if (localOpInfo.dataType != remoteOpInfo.dataType) {
1102 1 : status = InconsistentType::DATATYPE_INCONSISTENT;
1103 1 : return HCCL_SUCCESS;
1104 : }
1105 :
1106 2 : if (localOpInfo.reduceOp != remoteOpInfo.reduceOp) {
1107 0 : status = InconsistentType::REDUCETYPE_INCONSISTENT;
1108 0 : return HCCL_SUCCESS;
1109 : }
1110 :
1111 2 : if (localOpInfo.root != remoteOpInfo.root) {
1112 0 : status = InconsistentType::ROOT_INCONSISTENT;
1113 0 : return HCCL_SUCCESS;
1114 : }
1115 :
1116 2 : if (localOpInfo.opType != HcclCMDType::HCCL_CMD_ALLGATHER_V && localOpInfo.opType != HcclCMDType::HCCL_CMD_ALLTOALLV
1117 2 : && localOpInfo.opType != HcclCMDType::HCCL_CMD_ALLTOALLVC
1118 2 : && localOpInfo.opType != HcclCMDType::HCCL_CMD_REDUCE_SCATTER_V) {
1119 : // 仅对数据量均等的算子进行校验数据量count
1120 2 : if (localOpInfo.count != remoteOpInfo.count) {
1121 1 : status = InconsistentType::COUNT_INCONSISTENT;
1122 1 : return HCCL_SUCCESS;
1123 : }
1124 : }
1125 1 : status = InconsistentType::NO_INCONSISTENT;
1126 1 : return HCCL_SUCCESS;
1127 : }
1128 :
1129 5 : void Heartbeat::CheckRecvOpInfoList()
1130 : {
1131 5 : if (GetExternalInconsistentCheckSwitch() != InconsistentCheckMode::ON) {
1132 5 : return;
1133 : }
1134 : // 校验接收队列中接收到的opInfo
1135 0 : std::unique_lock<std::mutex> lock(opInfoMapMutex_);
1136 0 : for (auto it = recvOpInfoList_.begin(); it != recvOpInfoList_.end();) {
1137 0 : const auto& opInfoRecv = std::get<0>(*it);
1138 0 : const auto& identifier = std::get<1>(*it);
1139 0 : const auto& uid = std::get<2>(*it);
1140 0 : auto opInfoIndexMap = opInfoMap_.find(identifier);
1141 0 : if (opInfoIndexMap == opInfoMap_.end()) {
1142 0 : ++it;
1143 0 : HCCL_DEBUG(
1144 : "[Heartbeat]check recv not found. identifier[%s] index[%u]", identifier.c_str(), opInfoRecv.index);
1145 0 : continue;
1146 : }
1147 :
1148 0 : if (opInfoIndexMap->second.find(opInfoRecv.index) != opInfoIndexMap->second.end()) {
1149 0 : const auto& opInfo = opInfoIndexMap->second[opInfoRecv.index];
1150 0 : InconsistentType inconsistent = InconsistentType::NO_INCONSISTENT;
1151 0 : CheckIsSameOp(opInfo, opInfoRecv, inconsistent);
1152 0 : if (inconsistent != InconsistentType::NO_INCONSISTENT) {
1153 : // 当算子不匹配时,记录并打印ERROR日志并广播下发不一致错误给其他节点
1154 : char localInfo[LOG_TMPBUF_SIZE];
1155 0 : s32 ret = snprintf_s(
1156 : localInfo, LOG_TMPBUF_SIZE, LOG_TMPBUF_SIZE - 1U,
1157 0 : "node[%s] optype[%s] dataType[%s] reduceOp[%s] count[%d] root[%d]", FormatUId(uid_).c_str(),
1158 0 : GetCMDTypeEnumStr(opInfo.opType).c_str(), GetDataTypeEnumStr(opInfo.dataType).c_str(),
1159 0 : GetReduceOpEnumStr(opInfo.reduceOp).c_str(), opInfo.count, opInfo.root);
1160 0 : CHK_PRT_CONT(ret == -1, HCCL_ERROR("Failed to build log info"));
1161 : char remoteInfo[LOG_TMPBUF_SIZE];
1162 0 : ret = snprintf_s(
1163 : remoteInfo, LOG_TMPBUF_SIZE, LOG_TMPBUF_SIZE - 1U,
1164 0 : "node[%s] optype[%s] dataType[%s] reduceOp[%s] count[%lu] root[%u]", FormatUId(uid).c_str(),
1165 0 : GetCMDTypeEnumStr(opInfoRecv.opType).c_str(), GetDataTypeEnumStr(opInfoRecv.dataType).c_str(),
1166 0 : GetReduceOpEnumStr(opInfoRecv.reduceOp).c_str(), opInfoRecv.count, opInfoRecv.root);
1167 0 : CHK_PRT_CONT(ret == -1, HCCL_ERROR("Failed to build log info"));
1168 :
1169 0 : AddInconsistentOpRecord(
1170 0 : identifier, opInfo, inconsistent, std::string(localInfo), std::string(remoteInfo));
1171 0 : HCCL_ERROR(
1172 : "[Heartbeat]check opinfo inconsistent. identifier[%s] index[%u], "
1173 : "local(%s); remote(%s)",
1174 : identifier.c_str(), opInfoRecv.index, localInfo, remoteInfo);
1175 0 : SetStatus(uid_, uid_, HeartBeatStatus::HEARTBEAT_INCONSISTENT);
1176 : }
1177 : // 校验完成后删除收到的opInfo
1178 0 : it = recvOpInfoList_.erase(it);
1179 : } else {
1180 : // 若在opInfoIndexMap中没有找到相同index的算子,先跳到该记录,校验下一个收到的算子
1181 0 : ++it;
1182 : }
1183 : }
1184 0 : return;
1185 0 : }
1186 :
1187 4 : HcclResult Heartbeat::SendFrame(UIDType& dst, UIDType& crimer, UIDType& informer, HeartBeatStatus status)
1188 : {
1189 4 : HeartBeatFrame bf(uid_, dst, crimer, informer, status);
1190 4 : if (rankId2SocketMap_[dst].sendBuffer.size() > 0) {
1191 1 : if (status != HeartBeatStatus::HEARTBEAT_OK && rankId2SocketMap_[dst].sendBuffer.size() < MAX_SENDBUFF_SIZE) {
1192 1 : rankId2SocketMap_[dst].sendBuffer.push(bf);
1193 : }
1194 3 : while (rankId2SocketMap_[dst].sendBuffer.size() > 0) {
1195 2 : HeartBeatFrame hbf = rankId2SocketMap_[dst].sendBuffer.front();
1196 2 : u64 sendDis = sizeof(HeartBeatFrame) - rankId2SocketMap_[dst].restSize;
1197 2 : u64 compSize = 0;
1198 2 : HcclResult ret = rankId2SocketMap_[dst].socket->ISend(
1199 2 : reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(&hbf) + sendDis), rankId2SocketMap_[dst].restSize,
1200 : compSize);
1201 2 : if (ret != HCCL_SUCCESS) {
1202 0 : return ret;
1203 : }
1204 2 : if (rankId2SocketMap_[dst].restSize == compSize) {
1205 2 : rankId2SocketMap_[dst].sendBuffer.pop();
1206 2 : rankId2SocketMap_[dst].restSize = sizeof(HeartBeatFrame);
1207 2 : HCCL_DEBUG(
1208 : "[Heartbeat][SendFrame] Send Success, from [%s] to [%s] about [%s] by [%s] status[%d]",
1209 : FormatUId(uid_).c_str(), FormatUId(dst).c_str(), FormatUId(crimer).c_str(),
1210 : FormatUId(informer).c_str(), status);
1211 : } else {
1212 0 : rankId2SocketMap_[dst].restSize = rankId2SocketMap_[dst].restSize - compSize;
1213 0 : break;
1214 : }
1215 : }
1216 : } else {
1217 3 : u64 compSize = 0;
1218 3 : u32 expectSize = sizeof(HeartBeatFrame);
1219 3 : HcclResult ret = rankId2SocketMap_[dst].socket->ISend(&bf, expectSize, compSize);
1220 3 : if (ret != HCCL_SUCCESS) {
1221 0 : return ret;
1222 : }
1223 3 : if (compSize == expectSize) {
1224 2 : HCCL_DEBUG(
1225 : "[Heartbeat][SendFrame] Send Success, from [%s] to [%s] about [%s] by [%s] status[%d]",
1226 : FormatUId(uid_).c_str(), FormatUId(dst).c_str(), FormatUId(crimer).c_str(), FormatUId(informer).c_str(),
1227 : status);
1228 : } else {
1229 1 : HCCL_DEBUG(
1230 : "[Heartbeat][SendFrame] Send Not Complete, from [%s] to [%s] about [%s] by [%s] status[%d], "
1231 : "expectSize[%u], compSize[%u]",
1232 : FormatUId(uid_).c_str(), FormatUId(dst).c_str(), FormatUId(crimer).c_str(), FormatUId(informer).c_str(),
1233 : status, expectSize, compSize);
1234 1 : rankId2SocketMap_[dst].restSize = expectSize - compSize;
1235 1 : rankId2SocketMap_[dst].sendBuffer.push(bf);
1236 : }
1237 : }
1238 4 : return HCCL_SUCCESS;
1239 : }
1240 :
1241 0 : HcclResult Heartbeat::SendFrameWithOpCheck(
1242 : UIDType& dst, UIDType& crimer, UIDType& informer, HeartBeatStatus status,
1243 : const OpInfoTagQueueFrame& opInfoTagQueueFrame)
1244 : {
1245 0 : HeartBeatFrameWithOpCheck bf(uid_, dst, crimer, informer, status);
1246 0 : bf.opInfoTagQueueFrame = opInfoTagQueueFrame;
1247 :
1248 0 : if (rankId2SocketMap_[dst].sendBufferWithOpCheck.size() > 0) {
1249 0 : if (status != HeartBeatStatus::HEARTBEAT_OK
1250 0 : && rankId2SocketMap_[dst].sendBufferWithOpCheck.size() < MAX_SENDBUFF_SIZE) {
1251 0 : rankId2SocketMap_[dst].sendBufferWithOpCheck.push(bf);
1252 : }
1253 : } else {
1254 0 : rankId2SocketMap_[dst].sendBufferWithOpCheck.push(bf);
1255 0 : rankId2SocketMap_[dst].restSize = sizeof(HeartBeatFrameWithOpCheck);
1256 : }
1257 : // 查询到某个Dst的发送缓冲数据量
1258 0 : u32 unCompletedCount = 0; // 已经发送的loop次数
1259 0 : while (rankId2SocketMap_[dst].sendBufferWithOpCheck.size() > 0) {
1260 0 : HeartBeatFrameWithOpCheck hbf = rankId2SocketMap_[dst].sendBufferWithOpCheck.front();
1261 0 : u64 sendDis = sizeof(HeartBeatFrameWithOpCheck) - rankId2SocketMap_[dst].restSize;
1262 0 : u64 compSize = 0;
1263 0 : HcclResult ret = rankId2SocketMap_[dst].socket->ISend(
1264 0 : reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(&hbf) + sendDis), rankId2SocketMap_[dst].restSize,
1265 : compSize);
1266 0 : if (ret != HCCL_SUCCESS) {
1267 0 : return ret;
1268 : }
1269 0 : if (rankId2SocketMap_[dst].restSize == compSize) {
1270 0 : rankId2SocketMap_[dst].sendBufferWithOpCheck.pop();
1271 0 : rankId2SocketMap_[dst].restSize = sizeof(HeartBeatFrameWithOpCheck);
1272 0 : HCCL_DEBUG(
1273 : "[Heartbeat][%s] Send Success, from [%s] to [%s] about [%s] by [%s] status[%d]", __func__,
1274 : FormatUId(uid_).c_str(), FormatUId(dst).c_str(), FormatUId(crimer).c_str(), FormatUId(informer).c_str(),
1275 : status);
1276 : } else {
1277 0 : HCCL_DEBUG(
1278 : "[Heartbeat][%s] Send Not Complete, from [%s] to [%s] about [%s] by [%s] status[%d], expectSize[%u], "
1279 : "compSize[%u]",
1280 : __func__, FormatUId(uid_).c_str(), FormatUId(dst).c_str(), FormatUId(crimer).c_str(),
1281 : FormatUId(informer).c_str(), status, rankId2SocketMap_[dst].restSize, compSize);
1282 0 : rankId2SocketMap_[dst].restSize = rankId2SocketMap_[dst].restSize - compSize;
1283 0 : unCompletedCount++;
1284 0 : SaluSleep(ONE_HUNDRED_MICROSECOND_OF_USLEEP); // 100us
1285 : // 限制发送的循环此时,避免在send流程里死循环
1286 0 : if (unCompletedCount > HBFRAME_SEND_LOOP_MAX_NUM) {
1287 0 : break; // 120个loop约30毫秒
1288 : }
1289 : }
1290 : }
1291 0 : return HCCL_SUCCESS;
1292 : }
1293 :
1294 0 : HcclResult Heartbeat::RecvFrame(UIDType& src)
1295 : {
1296 0 : HeartBeatFrame bf;
1297 0 : u64 compSize = 0;
1298 0 : u64 expectSize = sizeof(HeartBeatFrame);
1299 : while (true) {
1300 0 : compSize = 0;
1301 0 : HcclResult retVal = rankId2SocketMap_[src].socket->IRecv(&bf, expectSize, compSize);
1302 0 : if (retVal == HCCL_SUCCESS && compSize > 0) {
1303 0 : rankId2SocketMap_[src].recvBuffer.PushSeg(reinterpret_cast<u8*>(&bf), compSize);
1304 0 : if (rankId2SocketMap_[src].recvBuffer.Size() >= expectSize) {
1305 0 : rankId2SocketMap_[src].recvBuffer.GetSeg(reinterpret_cast<u8*>(&bf), expectSize);
1306 0 : rankId2SocketMap_[src].recvBuffer.PopSeg(expectSize);
1307 0 : CHK_RET(ParseFrame(bf, src));
1308 : }
1309 0 : } else if (retVal == HCCL_E_INTERNAL) {
1310 0 : return HCCL_E_INTERNAL;
1311 : } else {
1312 0 : break;
1313 : }
1314 0 : }
1315 0 : return HCCL_SUCCESS;
1316 : }
1317 :
1318 0 : HcclResult Heartbeat::RecvFrameWithOpCheck(UIDType& src)
1319 : {
1320 0 : HeartBeatFrameWithOpCheck bf;
1321 0 : u64 compSize = 0;
1322 0 : u64 expectSize = sizeof(HeartBeatFrameWithOpCheck);
1323 : while (true) {
1324 0 : compSize = 0;
1325 0 : HcclResult retVal = rankId2SocketMap_[src].socket->IRecv(&bf, expectSize, compSize);
1326 0 : if (retVal == HCCL_SUCCESS && compSize > 0) {
1327 0 : rankId2SocketMap_[src].recvBuffer.PushSeg(reinterpret_cast<u8*>(&bf), compSize);
1328 : // 标识当前Recvbuf中已经存放了一个完整的帧
1329 0 : if (rankId2SocketMap_[src].recvBuffer.Size() >= expectSize) {
1330 0 : rankId2SocketMap_[src].recvBuffer.GetSeg(reinterpret_cast<u8*>(&bf), expectSize);
1331 0 : rankId2SocketMap_[src].recvBuffer.PopSeg(expectSize);
1332 0 : CHK_RET(ParseFrameWithOpCheck(bf, src));
1333 0 : break;
1334 : }
1335 0 : } else if (retVal == HCCL_E_INTERNAL) {
1336 0 : return HCCL_E_INTERNAL;
1337 : } else {
1338 0 : break;
1339 : }
1340 0 : }
1341 0 : return HCCL_SUCCESS;
1342 : }
1343 :
1344 2 : HcclResult Heartbeat::ParseFrame(HeartBeatFrame& bf, UIDType& src)
1345 : {
1346 2 : if (bf.src != src || bf.dst != uid_) {
1347 0 : HCCL_WARNING("rank[%s] recv wrong frame", FormatUId(uid_).c_str());
1348 0 : return HCCL_E_INTERNAL;
1349 : }
1350 :
1351 2 : HCCL_DEBUG(
1352 : "[Heartbeat][RecvFrame] Recv Success, from [%s] to [%s] about [%s] by [%s] state[%d]",
1353 : FormatUId(bf.src).c_str(), FormatUId(bf.dst).c_str(), FormatUId(bf.crimer).c_str(),
1354 : FormatUId(bf.informer).c_str(), bf.status);
1355 :
1356 : // 能够收到进程卡住表示心跳是正常的
1357 2 : if (bf.status == HeartBeatStatus::HEARTBEAT_OK || bf.status == HeartBeatStatus::HEARTBEAT_STUCK) {
1358 2 : rankId2SocketMap_[src].lostNum = 0;
1359 2 : rankId2SocketMap_[src].lostReportCnt = 0;
1360 : }
1361 :
1362 : // 只有心跳非正常时才需要打印TRACE
1363 2 : if (bf.status != HeartBeatStatus::HEARTBEAT_OK) {
1364 1 : SetStatus(bf.crimer, bf.informer, bf.status);
1365 : }
1366 :
1367 2 : return HCCL_SUCCESS;
1368 : }
1369 :
1370 2 : HcclResult Heartbeat::ParseFrameWithOpCheck(HeartBeatFrameWithOpCheck& bf, UIDType& src)
1371 : {
1372 2 : if (bf.src != src || bf.dst != uid_) {
1373 0 : HCCL_WARNING("rank[%s] recv wrong frame", FormatUId(uid_).c_str());
1374 0 : return HCCL_E_INTERNAL;
1375 : }
1376 :
1377 2 : HCCL_DEBUG(
1378 : "[Heartbeat][RecvFrame] Recv Success, from [%s] to [%s] about [%s] by [%s] state[%d]",
1379 : FormatUId(bf.src).c_str(), FormatUId(bf.dst).c_str(), FormatUId(bf.crimer).c_str(),
1380 : FormatUId(bf.informer).c_str(), bf.status);
1381 :
1382 2 : if (bf.status == HeartBeatStatus::HEARTBEAT_OK || bf.status == HeartBeatStatus::HEARTBEAT_STUCK) {
1383 2 : rankId2SocketMap_[src].lostNum = 0;
1384 2 : rankId2SocketMap_[src].lostReportCnt = 0;
1385 : }
1386 :
1387 2 : if (bf.status != HeartBeatStatus::HEARTBEAT_OK) {
1388 1 : SetStatus(bf.crimer, bf.informer, bf.status);
1389 : }
1390 :
1391 2 : SaveOpInfo(bf.opInfoTagQueueFrame, src);
1392 2 : return HCCL_SUCCESS;
1393 : }
1394 :
1395 7 : void Heartbeat::SetStatus(UIDType& crimer, UIDType& informer, HeartBeatStatus status, bool needBroadcast)
1396 : {
1397 7 : if (rankId2StatusMap_[crimer].status != status) {
1398 5 : rankId2StatusMap_[crimer].informer = informer;
1399 5 : rankId2StatusMap_[crimer].status = status;
1400 5 : rankId2StatusMap_[crimer].needBroadcast = needBroadcast;
1401 5 : if (needBroadcast) {
1402 1 : errRankQueue_.push(crimer);
1403 : }
1404 :
1405 5 : errStatusQueue_.push(HeartBeatFrame(crimer, informer, status, TIME_NOW(), std::chrono::system_clock::now()));
1406 5 : if (errStatusQueue_.size() > EVENT_MAX_CNT) {
1407 0 : errStatusQueue_.pop();
1408 : }
1409 5 : HCCL_RUN_INFO(
1410 : "[%s][%s]local rank [%s]: crimer rank [%s] status[%s] by informer rank [%s]",
1411 : LOG_KEYWORDS_TASK_EXEC.c_str(), LOG_KEYWORDS_HEARTBEAT_EVETN.c_str(), FormatUId(uid_).c_str(),
1412 : FormatUId(crimer).c_str(), GetHeartBeatStatusStr(status).c_str(), FormatUId(informer).c_str());
1413 : }
1414 7 : }
1415 :
1416 4 : bool Heartbeat::IsKeyEvent(HeartBeatFrame& event, HcclUs curTime, const std::string& group)
1417 : {
1418 4 : bool ret = false;
1419 4 : s64 intervalTime = DURATION_US(curTime - event.TOARelative).count() / (TIME_S_TO_MS * ONE_MILLISECOND_OF_USLEEP);
1420 4 : s32 hcclExecTimeout = CommConfiger::GetInstance().GetCommConfigExecTimeOut(group);
1421 4 : s64 execTimeout = hcclExecTimeout;
1422 4 : s64 detectionTime = 0;
1423 4 : switch (event.status) {
1424 1 : case HeartBeatStatus::HEARTBEAT_LOST:
1425 1 : detectionTime = (lostThreshold_ * HEARTBEAT_INTERVAL) / TIME_S_TO_MS;
1426 1 : break;
1427 3 : case HeartBeatStatus::HEARTBEAT_CQE_ERR:
1428 : case HeartBeatStatus::HEARTBEAT_INCONSISTENT:
1429 : case HeartBeatStatus::HEARTBEAT_OPRETRY_NOT_SUPPORT:
1430 3 : detectionTime = 0;
1431 3 : break;
1432 0 : case HeartBeatStatus::HEARTBEAT_STUCK:
1433 0 : detectionTime = 2 * stuckDetectTime_; // 最长探测时间为2倍的卡住检测时间
1434 0 : break;
1435 0 : case HeartBeatStatus::HEARTBEAT_NOTIFY:
1436 : default:
1437 0 : return false; // 当前不支持的事件,不做处理和展现
1438 : }
1439 8 : ret = ((execTimeout - intervalTime - detectionTime) < JITTER_TIME)
1440 4 : && ((intervalTime + detectionTime - execTimeout) < JITTER_TIME);
1441 4 : return ret;
1442 : }
1443 :
1444 96 : void Heartbeat::MakeErrMsg(std::queue<HeartBeatFrame>& keyEvents, std::vector<std::string>& errStatusVec)
1445 : {
1446 99 : while (keyEvents.size() > 0) {
1447 3 : auto& tmp = keyEvents.front();
1448 3 : std::string crimerStr = FormatUId(tmp.crimer);
1449 3 : std::string informerStr = FormatUId(tmp.informer);
1450 :
1451 6 : std::string headStr = "[" + LOG_KEYWORDS_TASK_EXEC + "][" + LOG_KEYWORDS_HEARTBEAT_EVETN + "]"
1452 3 : + "Cluster Exception Location[IP/ID]:[";
1453 :
1454 3 : time_t tm = std::chrono::system_clock::to_time_t(tmp.TOASystem);
1455 3 : std::string timeStr(ctime(&tm));
1456 3 : if (!timeStr.empty()) { // ctime()函数自带换行符,需要去掉
1457 3 : timeStr.pop_back();
1458 : }
1459 3 : timeStr = ", Arrival Time:[" + timeStr + "]";
1460 :
1461 6 : std::string errStr = ", ExceptionType:";
1462 3 : std::string reasonStr = ", Possible Reason:";
1463 3 : switch (tmp.status) {
1464 1 : case HeartBeatStatus::HEARTBEAT_LOST:
1465 1 : errStr = errStr + "[Heartbeat Lost Occurred]";
1466 1 : reasonStr = reasonStr + "1. Process has exited, 2. Network Disconnected";
1467 : errStr
1468 1 : = headStr + crimerStr + "]" + timeStr + ", Discoverer:[" + informerStr + "]" + errStr + reasonStr;
1469 1 : break;
1470 0 : case HeartBeatStatus::HEARTBEAT_NOTIFY:
1471 0 : errStr = errStr + "[Notify Wait Error Occurred]";
1472 0 : errStr = headStr + crimerStr + "]" + timeStr + errStr;
1473 0 : break;
1474 1 : case HeartBeatStatus::HEARTBEAT_OPRETRY_NOT_SUPPORT:
1475 1 : errStr = errStr + "[OpRetry Not Supported Occurred]";
1476 1 : reasonStr = reasonStr + "OpRetry is not supported";
1477 1 : errStr = headStr + crimerStr + "]" + timeStr + errStr + reasonStr;
1478 1 : break;
1479 1 : case HeartBeatStatus::HEARTBEAT_CQE_ERR:
1480 1 : errStr = errStr + "[Error cqe Occurred]";
1481 1 : reasonStr = reasonStr + "1.Network Disconnected, 2.Remote Rank Coredown";
1482 1 : errStr = headStr + crimerStr + "]" + timeStr + errStr + reasonStr;
1483 1 : break;
1484 0 : case HeartBeatStatus::HEARTBEAT_STUCK:
1485 0 : errStr = errStr + "[Stuck Occurred]";
1486 0 : reasonStr = reasonStr + "1.Host process is stuck, 2.Device task is stuck";
1487 0 : errStr = headStr + crimerStr + "]" + timeStr + errStr + reasonStr;
1488 0 : break;
1489 0 : case HeartBeatStatus::HEARTBEAT_INCONSISTENT:
1490 0 : errStr = errStr + "[Op Inconsistent Occurred]";
1491 0 : reasonStr = reasonStr + "communication operator is inconsistent";
1492 0 : errStr = headStr + crimerStr + "]" + timeStr + errStr + reasonStr;
1493 0 : break;
1494 0 : default:
1495 0 : errStr = " Unknown";
1496 : }
1497 3 : errStatusVec.emplace_back(errStr);
1498 3 : keyEvents.pop();
1499 3 : }
1500 96 : }
1501 19 : std::vector<std::string> Heartbeat::PrintEvents(std::map<HeartBeatStatus, std::queue<HeartBeatFrame>>& keyEvents)
1502 : {
1503 19 : std::vector<std::string> errStatusVec;
1504 : // 打印优先级 opretry not support > error cqe > stuck > lost
1505 19 : MakeErrMsg(keyEvents[HeartBeatStatus::HEARTBEAT_OPRETRY_NOT_SUPPORT], errStatusVec);
1506 19 : MakeErrMsg(keyEvents[HeartBeatStatus::HEARTBEAT_CQE_ERR], errStatusVec);
1507 19 : MakeErrMsg(keyEvents[HeartBeatStatus::HEARTBEAT_STUCK], errStatusVec);
1508 19 : MakeErrMsg(keyEvents[HeartBeatStatus::HEARTBEAT_LOST], errStatusVec);
1509 19 : MakeErrMsg(keyEvents[HeartBeatStatus::HEARTBEAT_INCONSISTENT], errStatusVec);
1510 19 : return errStatusVec;
1511 0 : }
1512 19 : std::vector<std::string> Heartbeat::GetErrStatusVec(const std::string& group)
1513 : {
1514 19 : std::unique_lock<std::mutex> lock(ProcessLock_);
1515 19 : HcclUs curTime = TIME_NOW();
1516 19 : std::map<HeartBeatStatus, std::queue<HeartBeatFrame>> keyEvents;
1517 22 : while (errStatusQueue_.size() > 0) {
1518 3 : auto& tmp = errStatusQueue_.front();
1519 3 : if (IsKeyEvent(tmp, curTime, group)) { // 非关键事件不处理
1520 2 : keyEvents[tmp.status].push(tmp);
1521 : }
1522 3 : errStatusQueue_.pop();
1523 : }
1524 38 : return PrintEvents(keyEvents);
1525 19 : }
1526 :
1527 4 : void Heartbeat::ProcessExceptionEvent()
1528 : {
1529 5 : while (errRankQueue_.size() > 0) {
1530 1 : UIDType cur = errRankQueue_.front();
1531 1 : rankId2StatusMap_[cur].needBroadcast = false;
1532 4989 : OpInfoTagQueueFrame opInfoTagQueueFrame;
1533 2 : for (auto iterRem = rankId2SocketMap_.begin(); iterRem != rankId2SocketMap_.end(); iterRem++) {
1534 1 : UIDType rem = iterRem->first;
1535 1 : if (rem != rankId2StatusMap_[cur].informer
1536 1 : && rankId2StatusMap_[rem].status == HeartBeatStatus::HEARTBEAT_OK) {
1537 1 : if (GetExternalInconsistentCheckSwitch() != InconsistentCheckMode::ON) {
1538 1 : (void)SendFrame(rem, cur, rankId2StatusMap_[cur].informer, rankId2StatusMap_[cur].status);
1539 : } else {
1540 0 : (void)SendFrameWithOpCheck(
1541 0 : rem, cur, rankId2StatusMap_[cur].informer, rankId2StatusMap_[cur].status, opInfoTagQueueFrame);
1542 : }
1543 : }
1544 : }
1545 1 : errRankQueue_.pop();
1546 : }
1547 4 : }
1548 :
1549 3 : void Heartbeat::CreateHBLinksAsync()
1550 : {
1551 3 : std::unique_lock<std::mutex> infoLock(hbLinkConnInfoMtx_);
1552 3 : if (hbLinkConnInfo_.empty()) {
1553 3 : return;
1554 : }
1555 0 : linkThreadRunning_ = true;
1556 0 : std::queue<std::tuple<std::string, UIDType, ConnInfo>> connInfoQueue;
1557 0 : for (auto& pair : hbLinkConnInfo_) {
1558 0 : const std::string& groupName = pair.first;
1559 0 : auto& groupConnInfoQueue = pair.second;
1560 0 : while (!groupConnInfoQueue.empty()) {
1561 0 : connInfoQueue.push(
1562 0 : std::make_tuple(groupName, groupConnInfoQueue.front().first, groupConnInfoQueue.front().second));
1563 0 : groupConnInfoQueue.pop();
1564 : }
1565 : }
1566 0 : infoLock.unlock();
1567 0 : while (!connInfoQueue.empty()) {
1568 0 : const std::string groupName = std::get<0>(connInfoQueue.front());
1569 0 : const UIDType& remUid = std::get<1>(connInfoQueue.front());
1570 0 : ConnInfo& connInfo = std::get<2>(connInfoQueue.front());
1571 0 : auto it = linkThreadMap_.find(remUid);
1572 0 : if (it != linkThreadMap_.end() && it->second->joinable()) {
1573 0 : it->second->join();
1574 0 : HCCL_INFO(
1575 : "[CreateHBLinksAsync] Heartbeat link thread has been joined. Group[%s], remote uid[%s].",
1576 : groupName.c_str(), FormatUId(remUid).c_str());
1577 : }
1578 0 : linkThreadMap_[remUid].reset(new (std::nothrow) std::thread(
1579 0 : &Heartbeat::CreateLinkWithRemote, std::ref(*this), groupName, remUid, connInfo));
1580 0 : if (linkThreadMap_[remUid] == nullptr) {
1581 0 : HCCL_RUN_WARNING(
1582 : "Group[%s] establish rank[%s] to rank[%s] heartbeat connection failed. Reason: "
1583 : "create thread failed.",
1584 : groupName.c_str(), FormatUId(uid_).c_str(), FormatUId(remUid).c_str());
1585 : }
1586 0 : connInfoQueue.pop();
1587 0 : }
1588 0 : return;
1589 3 : }
1590 :
1591 7 : void Heartbeat::HeartbeatStatusMonitor()
1592 : {
1593 : // 给当前线程添加名字
1594 7 : SetThreadName("Hccl_HeartBeat");
1595 :
1596 7 : u32 count = 0;
1597 7 : if (deviceLogicId_ != static_cast<u32>(HOST_DEVICE_ID)) {
1598 3 : hrtSetDevice(deviceLogicId_);
1599 : }
1600 7 : uint64_t cnt = 0;
1601 : HcclResult ret;
1602 7 : auto counterStat = CounterStat();
1603 7 : InitStuckDetection(counterStat);
1604 16 : while (startSendRecvTask_) {
1605 9 : CheckSnapshotStatus();
1606 9 : if (isPaused_) {
1607 0 : std::this_thread::sleep_for(std::chrono::milliseconds(BROADCAST_INTERVAL));
1608 0 : continue;
1609 : }
1610 9 : CreateHBLinksAsync();
1611 9 : ProcessLock_.lock();
1612 9 : count++;
1613 9 : if (count >= HEARTBEAT_COUNT) {
1614 0 : count = 0;
1615 0 : OpInfoTagQueueFrame opInfoTagQueueFrame;
1616 0 : GetSendOpInfoList(opInfoTagQueueFrame);
1617 0 : for (auto iter = rankId2SocketMap_.begin(); iter != rankId2SocketMap_.end(); iter++) {
1618 0 : UIDType rem = iter->first;
1619 0 : HCCL_DEBUG(
1620 : "rank[%s] Try to Send HeartBeat to rank[%s]", FormatUId(uid_).c_str(), FormatUId(rem).c_str());
1621 0 : rankId2SocketMap_[rem].lostNum++;
1622 0 : HeartBeatStatus status = HeartBeatStatus::HEARTBEAT_OK;
1623 0 : if (counterStat.issueCnt != 0) {
1624 0 : status = HeartBeatStatus::HEARTBEAT_STUCK;
1625 : }
1626 0 : if (GetExternalInconsistentCheckSwitch() != InconsistentCheckMode::ON) {
1627 0 : ret = SendFrame(rem, uid_, uid_, status);
1628 : } else {
1629 0 : ret = SendFrameWithOpCheck(rem, uid_, uid_, status, opInfoTagQueueFrame);
1630 : }
1631 0 : if (ret == HCCL_E_INTERNAL) {
1632 0 : errorSocket_.push_back(rem);
1633 : }
1634 : }
1635 0 : DelErrorSocket();
1636 0 : ProcessCqeErrInfo();
1637 0 : if (counterStat.issueCnt != 0) {
1638 0 : SetStatus(uid_, uid_, HeartBeatStatus::HEARTBEAT_STUCK);
1639 : }
1640 : }
1641 :
1642 21 : for (auto iter = rankId2SocketMap_.begin(); iter != rankId2SocketMap_.end(); iter++) {
1643 12 : UIDType rem = iter->first;
1644 12 : HCCL_DEBUG("rank[%s] Try to Recv from rank[%s]", FormatUId(uid_).c_str(), FormatUId(rem).c_str());
1645 12 : ret = (GetExternalInconsistentCheckSwitch() != InconsistentCheckMode::ON) ? RecvFrame(rem) :
1646 0 : RecvFrameWithOpCheck(rem);
1647 12 : if (ret == HCCL_E_INTERNAL) {
1648 0 : errorSocket_.push_back(rem);
1649 0 : continue;
1650 : }
1651 12 : uint32_t threshold = lostThreshold_ << rankId2SocketMap_[rem].lostReportCnt; // LOST帧发送周期放长
1652 12 : if (rankId2SocketMap_[rem].lostNum >= threshold) {
1653 1 : SetStatus(rem, uid_, HeartBeatStatus::HEARTBEAT_LOST);
1654 1 : rankId2SocketMap_[rem].lostReportCnt++;
1655 : }
1656 : }
1657 9 : CheckRecvOpInfoList();
1658 9 : DelErrorSocket();
1659 9 : StuckDetection(cnt, counterStat);
1660 9 : ProcessExceptionEvent();
1661 9 : ProcessLock_.unlock();
1662 :
1663 9 : auto sleeptime = (GetExternalInconsistentCheckSwitch() != InconsistentCheckMode::ON) ?
1664 : BROADCAST_INTERVAL :
1665 9 : BROADCAST_INTERVAL_WITH_CHECK;
1666 9 : std::this_thread::sleep_for(std::chrono::milliseconds(sleeptime));
1667 : }
1668 7 : linkThreadRunning_ = false;
1669 : // 在心跳进程结束之前join所有的建链线程
1670 7 : for (auto& pair : linkThreadMap_) {
1671 0 : if (pair.second != nullptr && pair.second->joinable()) {
1672 0 : pair.second->join();
1673 0 : HCCL_INFO("[HeartbeatStatusMonitor] thread has joined. Remote uid is [%s]", FormatUId(pair.first).c_str());
1674 : }
1675 : }
1676 :
1677 7 : if (deviceLogicId_ != static_cast<u32>(HOST_DEVICE_ID)) {
1678 3 : hrtResetDevice(deviceLogicId_);
1679 : }
1680 7 : }
1681 :
1682 7 : void Heartbeat::InitStuckDetection(CounterStat& counterStat)
1683 : {
1684 7 : counterStat.isNeedDetect = (GetExternalInputStuckDetect() == true) ? true : false;
1685 7 : counterStat.couterPrintInter = stuckDetectTime_ * THROUND_MILS / BROADCAST_INTERVAL;
1686 7 : }
1687 :
1688 5 : void Heartbeat::StuckDetection(uint64_t& cnt, CounterStat& counterStat)
1689 : {
1690 5 : HCCL_DEBUG(
1691 : "cnt: %d, isNeedDetect: %d, issueCnt:%llu, interTimes:%d", cnt, counterStat.isNeedDetect, counterStat.issueCnt,
1692 : counterStat.couterPrintInter);
1693 5 : cnt++;
1694 5 : HcclResult ret = HCCL_SUCCESS;
1695 5 : if (counterStat.isNeedDetect && cnt % counterStat.couterPrintInter == 0) {
1696 2 : if (counterStat.isFirst) {
1697 1 : OpExeCounter::GetInstance(deviceLogicId_).GetCounter(counterStat.oldCounter);
1698 1 : counterStat.isFirst = false;
1699 : } else {
1700 1 : ret = OpExeCounter::GetInstance(deviceLogicId_).GetCounter(counterStat.newCounter);
1701 1 : if (ret == HCCL_SUCCESS && counterStat.newCounter.first == counterStat.oldCounter.first
1702 1 : && counterStat.newCounter.first == counterStat.oldCounter.second
1703 1 : && counterStat.newCounter.first == counterStat.newCounter.second) {
1704 1 : HCCL_RUN_INFO(
1705 : "[HCCL_TRACE]rank:%s, count of currently executed operators:%d", FormatUId(uid_).c_str(),
1706 : counterStat.newCounter.first);
1707 1 : counterStat.couterPrintInter *= (BASE_NUMBER << counterStat.issueCnt); // 检测卡住后,把检测周期放长
1708 1 : counterStat.issueCnt++;
1709 : } else {
1710 : // 检测不卡之后,检测间隔恢复到默认间隔
1711 0 : counterStat.couterPrintInter = stuckDetectTime_ * THROUND_MILS / BROADCAST_INTERVAL;
1712 0 : counterStat.issueCnt = 0;
1713 : }
1714 1 : counterStat.oldCounter = counterStat.newCounter; // 更新旧的计数器
1715 : }
1716 : }
1717 5 : }
1718 :
1719 1 : void Heartbeat::PrintAndBroadCastErrorCqe(const ErrCqeInfo& info)
1720 : {
1721 : time_t tmpt;
1722 : struct tm* now;
1723 1 : if (info.cqeInfo.status == 0) {
1724 0 : return;
1725 : }
1726 :
1727 1 : SetStatus(uid_, uid_, HeartBeatStatus::HEARTBEAT_CQE_ERR);
1728 1 : tmpt = static_cast<time_t>(info.cqeInfo.time.tv_sec);
1729 1 : now = localtime(&tmpt);
1730 :
1731 : char errorLinkLogBuffer[LOG_TMPBUF_SIZE];
1732 3 : s32 stringRet = snprintf_s(
1733 : errorLinkLogBuffer, LOG_TMPBUF_SIZE, LOG_TMPBUF_SIZE - 1U,
1734 : "localInfo{server[%s],deviceId[%d],deviceIp[%s]}, remoteIP{server[%s],deviceId[%d],deviceIp[%s]}",
1735 1 : info.linkInfo.localServerId.c_str(), info.linkInfo.localDevicePhyId, nicIp_.GetReadableAddress(),
1736 1 : info.linkInfo.remoteServerId.c_str(), info.linkInfo.remoteDevicePhyId,
1737 : info.cqeInfo.remoteIp.GetReadableAddress());
1738 1 : CHK_PRT_CONT(stringRet == -1, HCCL_ERROR("[Create][DestLink]Transport init error! Failed to build log info"));
1739 :
1740 1 : if (now == nullptr) {
1741 0 : HCCL_ERROR(
1742 : "[%s][%s][%s]localtime fail, cqe error status[%u], %s", LOG_KEYWORDS_TASK_EXEC.c_str(),
1743 : LOG_KEYWORDS_HEARTBEAT_EVETN.c_str(), LOG_KEYWORDS_CQE_ERROR.c_str(), info.cqeInfo.status,
1744 : errorLinkLogBuffer);
1745 : } else {
1746 1 : HCCL_ERROR(
1747 : "[%s][%s][%s]cqe error status[%u], time:[%04u-%02d-%02d %02d:%0d:%02d.%06u], %s",
1748 : LOG_KEYWORDS_TASK_EXEC.c_str(), LOG_KEYWORDS_HEARTBEAT_EVETN.c_str(), LOG_KEYWORDS_CQE_ERROR.c_str(),
1749 : info.cqeInfo.status, now->tm_year + TIME_FROM_1900, now->tm_mon + 1, now->tm_mday, now->tm_hour,
1750 : now->tm_min, now->tm_sec, static_cast<u32>(info.cqeInfo.time.tv_usec), errorLinkLogBuffer);
1751 : }
1752 :
1753 1 : std::unique_lock<std::mutex> lock(remoteIpMutex_);
1754 1 : auto search = remoteIpMap.find(info.linkInfo.identifier);
1755 1 : if (search != remoteIpMap.end()) {
1756 0 : remoteIpMap[info.linkInfo.identifier].insert(info);
1757 : } else {
1758 1 : std::set<ErrCqeInfo> remoteInfoSet;
1759 1 : remoteInfoSet.insert(info);
1760 1 : remoteIpMap.insert(std::pair<std::string, std::set<ErrCqeInfo>>(info.linkInfo.identifier, remoteInfoSet));
1761 1 : }
1762 1 : }
1763 :
1764 6 : void Heartbeat::SaveQpnForOpRetry(const ErrCqeInfo& info)
1765 : {
1766 6 : if (info.cqeInfo.status == 0) {
1767 2 : return;
1768 : }
1769 :
1770 4 : HCCL_RUN_INFO(
1771 : "[Heartbeat][SaveQpnForOpRetry]receive a cqe error [%u][%u], dstrank[%u] identifier[%s]", info.cqeInfo.status,
1772 : info.qpn, info.linkInfo.remoteRank, info.linkInfo.identifier.c_str());
1773 4 : auto identiSearch = rankMapForRetryAgent.find(info.linkInfo.identifier);
1774 4 : if (identiSearch != rankMapForRetryAgent.end()) {
1775 3 : auto rankSearch = identiSearch->second.find(info.linkInfo.remoteRank);
1776 3 : if (rankSearch != identiSearch->second.end()) {
1777 2 : (*rankSearch).second.insert(info);
1778 : } else {
1779 4 : identiSearch->second.insert({info.linkInfo.remoteRank, {info}});
1780 : }
1781 : } else {
1782 1 : std::map<u32, std::set<ErrCqeInfo>> rankExtendMap;
1783 2 : rankExtendMap[info.linkInfo.remoteRank] = {info};
1784 1 : rankMapForRetryAgent.insert(std::make_pair(info.linkInfo.identifier, rankExtendMap));
1785 1 : }
1786 2 : }
1787 :
1788 0 : void Heartbeat::OpRetryCQEHandle(const HcclNetDevCtx netDevCtx)
1789 : {
1790 0 : u32 cqeNum = RETRY_CQE_ARRAY_SIZE;
1791 : do {
1792 0 : cqeNum = RETRY_CQE_ARRAY_SIZE;
1793 :
1794 0 : std::vector<ErrCqeInfo> infos;
1795 0 : HcclResult ret = HcclCommunicator::GetTransportCqeErrors(netDevCtx, infos, cqeNum);
1796 0 : if (ret != HCCL_SUCCESS || cqeNum == 0) {
1797 0 : return;
1798 : }
1799 0 : for (auto& info : infos) {
1800 0 : if (GetRetryEnable(info)
1801 0 : && CommConfiger::GetInstance().GetCommConfigInterSuperPodRetryEnable(info.linkInfo.identifier)) {
1802 0 : SaveQpnForOpRetry(info);
1803 : } else {
1804 0 : PrintAndBroadCastErrorCqe(info);
1805 : }
1806 : }
1807 0 : } while (cqeNum == RETRY_CQE_ARRAY_SIZE);
1808 : }
1809 :
1810 0 : bool Heartbeat::GetRetryEnable(const ErrCqeInfo& info)
1811 : {
1812 0 : std::lock_guard<std::mutex> retryEnablelock(retryEnableMutex_);
1813 0 : auto search = retryEnableTable_.find(info.linkInfo.identifier);
1814 0 : if (search != retryEnableTable_.end()) {
1815 0 : return search->second;
1816 : }
1817 0 : return false;
1818 0 : }
1819 800 : HcclResult Heartbeat::ClearRetryEnableMapItem(const std::string& identifier)
1820 : {
1821 800 : CHK_PRT_RET(initialized_ == false, HCCL_WARNING("Heartbeat has been destroyed"), HCCL_SUCCESS);
1822 0 : u32 delRes = 0;
1823 : {
1824 0 : std::lock_guard<std::mutex> retryEnablelock(retryEnableMutex_);
1825 0 : delRes = retryEnableTable_.erase(identifier);
1826 0 : if (delRes != 0) {
1827 0 : HCCL_INFO("[Heartbeat][ClearRetryEnableMapItem] del identifier[%s] succ", identifier.c_str());
1828 : } else {
1829 0 : HCCL_DEBUG("[Heartbeat][ClearRetryEnableMapItem] identifier[%s] is not found.", identifier.c_str());
1830 : }
1831 0 : }
1832 0 : std::lock_guard<std::mutex> bakcupEnablelock(backupEnableMutex_);
1833 0 : delRes = backupEnableTable_.erase(identifier);
1834 0 : if (delRes != 0) {
1835 0 : HCCL_INFO("[Heartbeat][ClearRetryEnableMapItem] del backup identifier[%s] succ", identifier.c_str());
1836 : } else {
1837 0 : HCCL_DEBUG("[Heartbeat][ClearRetryEnableMapItem] identifier[%s] is not found.", identifier.c_str());
1838 : }
1839 0 : return HCCL_SUCCESS;
1840 0 : }
1841 21 : void Heartbeat::ProcessCqeErrInfoByNetDevCtx(const HcclIpAddress& nicIp)
1842 : {
1843 21 : std::unique_lock<std::mutex> mapLock(ctxMapMutex_);
1844 21 : auto iter = netDevCtxMap_.find(nicIp);
1845 21 : if (iter == netDevCtxMap_.end() || netDevCtxMap_[nicIp] == nullptr) {
1846 7 : return;
1847 : }
1848 14 : mapLock.unlock();
1849 14 : const HcclNetDevCtx netDevCtx = iter->second;
1850 14 : std::vector<ErrCqeInfo> infos;
1851 14 : u32 cqeNum = 1;
1852 14 : HcclResult ret = HcclCommunicator::GetTransportCqeErrors(netDevCtx, infos, cqeNum);
1853 14 : if (ret != HCCL_SUCCESS || infos.size() == 0) {
1854 14 : return;
1855 : }
1856 0 : if (GetRetryEnable(infos[0])
1857 0 : && CommConfiger::GetInstance().GetCommConfigInterSuperPodRetryEnable(infos[0].linkInfo.identifier)) {
1858 0 : SaveQpnForOpRetry(infos[0]);
1859 : } else {
1860 0 : PrintAndBroadCastErrorCqe(infos[0]);
1861 : }
1862 : // infoList 处理
1863 0 : OpRetryCQEHandle(netDevCtx);
1864 35 : }
1865 :
1866 20 : void Heartbeat::ProcessCqeErrInfo()
1867 : {
1868 20 : ProcessCqeErrInfoByNetDevCtx(nicIp_);
1869 20 : if (IsEnableBackupLink()) {
1870 1 : ProcessCqeErrInfoByNetDevCtx(backupNicIp_);
1871 : }
1872 20 : }
1873 :
1874 3 : void Heartbeat::DelErrorSocket()
1875 : {
1876 3 : for (auto rem : errorSocket_) {
1877 0 : HCCL_RUN_INFO(
1878 : "rank[%s] Try to Send/recv HeartBeat to rank[%s]", FormatUId(uid_).c_str(), FormatUId(rem).c_str());
1879 0 : rankId2StatusMap_.erase(rem);
1880 0 : if (rankId2SocketMap_.has(rem)) {
1881 0 : if (rankId2SocketMap_[rem].socket->GetLocalRole() == HcclSocketRole::SOCKET_ROLE_SERVER
1882 0 : && listenSocketMap_.find(rankId2SocketMap_[rem].socket->GetLocalIp()) != listenSocketMap_.end()) {
1883 0 : listenSocketMap_[rankId2SocketMap_[rem].socket->GetLocalIp()]->DelWhiteList(
1884 0 : rankId2SocketMap_[rem].wlistInfosVec);
1885 : }
1886 0 : rankId2SocketMap_[rem].socket->Close();
1887 0 : while (rankId2SocketMap_.erase(rem)) {
1888 : };
1889 : }
1890 : }
1891 3 : errorSocket_.clear();
1892 3 : }
1893 :
1894 2 : HcclResult Heartbeat::GetQpnErr(const std::string& identifier, std::set<std::tuple<u32, u32, u32>>& qpErrSet)
1895 : {
1896 2 : std::unique_lock<std::mutex> lock(qpnMapMutexForRetry_);
1897 2 : auto search = rankMapForRetryAgent.find(identifier);
1898 2 : if (search == rankMapForRetryAgent.end()) {
1899 1 : HCCL_INFO("[GetQpnErr]identifier[%s] is not found", identifier.c_str());
1900 1 : return HCCL_SUCCESS;
1901 : }
1902 1 : if (search->second.size() > 0) {
1903 2 : for (auto iter : search->second) {
1904 1 : u32 dstRank = iter.first;
1905 2 : for (auto qpnInfo : iter.second) {
1906 1 : u32 status = qpnInfo.cqeInfo.status;
1907 1 : qpErrSet.insert(std::make_tuple(dstRank, status, qpnInfo.qpn));
1908 1 : }
1909 1 : }
1910 : }
1911 1 : HCCL_INFO("[GetQpnErr]identifier[%s] is found, qpErrSet size is %u", identifier.c_str(), qpErrSet.size());
1912 1 : return HCCL_SUCCESS;
1913 2 : }
1914 : // OpRetry 失败后,将进行广播操作
1915 1 : HcclResult Heartbeat::BroadcastCqeErr(const std::string& identifier)
1916 : {
1917 1 : u32 cqeSize = 0;
1918 1 : std::unique_lock<std::mutex> qpnMaplock(qpnMapMutexForRetry_);
1919 1 : auto search = rankMapForRetryAgent.find(identifier);
1920 1 : if (search != rankMapForRetryAgent.end()) {
1921 1 : if (search->second.size() > 0) {
1922 1 : cqeSize = search->second.size();
1923 2 : for (auto& qpInfo : search->second) {
1924 2 : for (auto qpnset : qpInfo.second) {
1925 1 : PrintAndBroadCastErrorCqe(qpnset);
1926 1 : HCCL_RUN_INFO(
1927 : "[BroadcastCqeErr][item]remoteIp[%s] remoteRank[%u] status[%u] qpn[%u]",
1928 : qpnset.cqeInfo.remoteIp.GetReadableAddress(), qpInfo.first, qpnset.cqeInfo.status, qpnset.qpn);
1929 1 : }
1930 : }
1931 1 : search->second.clear();
1932 : }
1933 : }
1934 : // 查询剩余量,一般为0
1935 1 : HCCL_RUN_INFO(
1936 : "[Heartbeat][BroadcastCqeErr]clear qpn err size from [%u] to [%u], identifier[%s] ", cqeSize,
1937 : search->second.size(), identifier.c_str());
1938 1 : return HCCL_SUCCESS;
1939 1 : }
1940 :
1941 : /* 非点对点通信 重执行成功后进行调用 */
1942 1 : HcclResult Heartbeat::ClearAllCqeErr(const std::string& identifier)
1943 : {
1944 1 : std::unique_lock<std::mutex> qpnMaplock(qpnMapMutexForRetry_);
1945 1 : u32 cqeSize = 0;
1946 1 : auto search = rankMapForRetryAgent.find(identifier);
1947 1 : if (search != rankMapForRetryAgent.end()) {
1948 1 : if (search->second.size() > 0) {
1949 0 : cqeSize = search->second.size();
1950 0 : search->second.clear();
1951 : }
1952 : }
1953 : // 查询剩余量,一般为0
1954 1 : HCCL_RUN_INFO(
1955 : "[Heartbeat][ClearAllCqeErr]clear qpn err size from [%u] to [%u], identifier[%s]", cqeSize,
1956 : search->second.size(), identifier.c_str());
1957 1 : return HCCL_SUCCESS;
1958 1 : }
1959 : /* 点对点通信 重执行成功后进行调用
1960 : */
1961 5 : HcclResult Heartbeat::ClearCqeErr(const std::string& identifier, u32 remoteRank, u32 qpn)
1962 : {
1963 5 : HCCL_RUN_INFO(
1964 : "[Heartbeat][ClearCqeErr] identifier[%s] remoteRank[%u] qpn[%u].", identifier.c_str(), remoteRank, qpn);
1965 5 : std::unique_lock<std::mutex> qpnMaplock(qpnMapMutexForRetry_);
1966 5 : const auto& search = rankMapForRetryAgent.find(identifier);
1967 5 : if (search == rankMapForRetryAgent.end()) {
1968 0 : return HCCL_SUCCESS;
1969 : }
1970 :
1971 5 : auto& ranksearch = rankMapForRetryAgent[identifier];
1972 : // 删除指定通信域内的固定 remoteRank 固定qpn的cqe err
1973 5 : if (ranksearch.find(remoteRank) != ranksearch.end()) {
1974 2 : if (ranksearch[remoteRank].size() == 1) {
1975 : // remotrank只有一个qpn err,直接删除map
1976 1 : ranksearch.erase(remoteRank);
1977 1 : HCCL_RUN_INFO("[ClearCqeErr][qpnClear] clear dstRank[%u] qpn[%u] now", remoteRank, qpn);
1978 1 : } else if (ranksearch[remoteRank].size() > 1) {
1979 3 : for (auto iter = ranksearch[remoteRank].begin(); iter != ranksearch[remoteRank].end();) {
1980 2 : if (iter->qpn == qpn) {
1981 1 : iter = ranksearch[remoteRank].erase(iter);
1982 1 : HCCL_RUN_INFO("[ClearCqeErr][qpnClear] clear dstRank[%u] qpn[%u] now", remoteRank, qpn);
1983 : } else {
1984 1 : ++iter;
1985 : }
1986 : }
1987 : }
1988 : }
1989 :
1990 : // 查询指定通信域剩余的 QP ERROR 数量
1991 5 : HCCL_RUN_INFO("[ClearCqeErr][qpnClear]identifier qpn err left [%u] now.", search->second.size());
1992 5 : return HCCL_SUCCESS;
1993 5 : }
1994 :
1995 3 : HcclResult Heartbeat::CheckErrorCqe(const std::string& identifier, HcclResult& result)
1996 : {
1997 3 : HcclIpAddress ip;
1998 3 : result = HCCL_SUCCESS;
1999 :
2000 3 : std::unique_lock<std::mutex> lock(remoteIpMutex_);
2001 3 : auto search = remoteIpMap.find(identifier);
2002 3 : if (search == remoteIpMap.end()) {
2003 2 : if (qpnDissociativeSet.size() != 0) { // 如果没有发生error cqe异常的通信域,则确认是否存在游离(Destroy)qpn
2004 0 : HCCL_ERROR(
2005 : "[Heartbeat]find cqe error [%d] num[%llu] dissociative. maybe its qp has already been destroyed",
2006 : result, qpnDissociativeSet.size());
2007 0 : qpnDissociativeSet.clear();
2008 0 : return HCCL_E_REMOTE;
2009 : }
2010 2 : return HCCL_SUCCESS;
2011 : }
2012 1 : if (search->second.size() > 0) {
2013 1 : result = HCCL_E_REMOTE;
2014 1 : HCCL_ERROR("[Heartbeat]find cqe error [%d], in comm [%s]", result, identifier.c_str());
2015 2 : for (auto& it : search->second) {
2016 1 : HCCL_ERROR(
2017 : "[Heartbeat]find cqe error, localIP[%s], remoteIP[%s]", nicIp_.GetReadableAddress(),
2018 : it.cqeInfo.remoteIp.GetReadableAddress());
2019 23 : RPT_INPUT_ERR(
2020 : true, "EI0013",
2021 : std::vector<std::string>(
2022 : {"localServerId", "localDeviceId", "localDeviceIp", "remoteServerId", "remoteDeviceId",
2023 : "remoteDeviceIp"}),
2024 : std::vector<std::string>(
2025 : {it.linkInfo.localServerId, std::to_string(it.linkInfo.localDevicePhyId),
2026 : std::string(nicIp_.GetReadableAddress()), it.linkInfo.remoteServerId,
2027 : std::to_string(it.linkInfo.remoteDevicePhyId),
2028 : std::string(it.cqeInfo.remoteIp.GetReadableAddress())}));
2029 : }
2030 : }
2031 1 : lock.unlock();
2032 :
2033 1 : return HCCL_SUCCESS;
2034 5 : }
2035 :
2036 0 : void Heartbeat::RegisterSROpIdentifier(const std::string& identifier, const std::string& paramTag)
2037 : {
2038 : // SR算子通信域映射关系注册
2039 0 : std::lock_guard<std::mutex> lock(srTagMutex_);
2040 0 : if (srTagMap_.size() > SR_TAG_MAP_MAX_NUM) {
2041 0 : srTagMap_.erase(srTagMap_.begin());
2042 : }
2043 :
2044 0 : auto iter = srTagMap_.find(paramTag);
2045 0 : if (iter == srTagMap_.end()) {
2046 0 : srTagMap_.insert(std::make_pair(paramTag, identifier));
2047 : }
2048 0 : }
2049 :
2050 0 : void Heartbeat::AddInconsistentOpRecord(
2051 : const std::string& identifier, const OpInfoDesc& localOpInfo, InconsistentType status, const std::string& localInfo,
2052 : const std::string& remoteInfo)
2053 : {
2054 0 : std::lock_guard<std::mutex> lock(inconsistentOpMutex_);
2055 0 : if (localOpInfo.opType == HcclCMDType::HCCL_CMD_SEND || localOpInfo.opType == HcclCMDType::HCCL_CMD_RECEIVE) {
2056 0 : auto iter = srTagMap_.find(identifier);
2057 0 : if (iter == srTagMap_.end()) {
2058 0 : HCCL_ERROR(
2059 : "[%s] SR tag[%s] may have already been deleted due to prolonged storage time", __func__,
2060 : identifier.c_str());
2061 0 : return;
2062 : }
2063 :
2064 0 : auto search = inconsistentOpMap_.find(iter->second); // SR tag
2065 0 : if (search == inconsistentOpMap_.end()) {
2066 0 : inconsistentOpMap_.insert(
2067 0 : std::make_pair(iter->second, OpInconsistentInfo(status, localInfo, remoteInfo, localOpInfo)));
2068 0 : HCCL_INFO(
2069 : "[%s] save record SR[%s] identifier[%s] index[%d]", __func__, identifier.c_str(), iter->second.c_str(),
2070 : localOpInfo.index);
2071 : }
2072 0 : } else {
2073 0 : auto search = inconsistentOpMap_.find(identifier); // AR identifier
2074 0 : if (search == inconsistentOpMap_.end()) {
2075 0 : inconsistentOpMap_.insert(
2076 0 : std::make_pair(identifier, OpInconsistentInfo(status, localInfo, remoteInfo, localOpInfo)));
2077 0 : HCCL_INFO("[%s] save record identifier[%s] index[%d]", __func__, identifier.c_str(), localOpInfo.index);
2078 : }
2079 : }
2080 0 : }
2081 :
2082 0 : HcclResult Heartbeat::CheckOpInconsistentError(const std::string& identifier, HcclResult& result)
2083 : {
2084 0 : if (GetExternalInconsistentCheckSwitch() != InconsistentCheckMode::ON) {
2085 0 : return HCCL_SUCCESS;
2086 : }
2087 0 : std::lock_guard<std::mutex> lock(inconsistentOpMutex_);
2088 0 : auto search = inconsistentOpMap_.find(identifier);
2089 0 : if (search != inconsistentOpMap_.end()) {
2090 0 : result = HCCL_E_PARA;
2091 0 : const OpInconsistentInfo& inconsistentInfo = search->second;
2092 0 : std::string opInfo = "Unknown";
2093 0 : for (const auto& pair : HCCL_OPTYPE_NAME_MAP) {
2094 0 : if (pair.second == inconsistentInfo.opInfoDesc.opType) {
2095 0 : opInfo = std::string(pair.first);
2096 0 : break;
2097 : }
2098 : }
2099 0 : HCCL_ERROR(
2100 : "[%s]find inconsistent op [%s] error [%d], in comm [%s]", __func__, opInfo, result, identifier.c_str());
2101 0 : RPT_INPUT_ERR(
2102 : true, "EI0005", std::vector<std::string>({"ccl_op", "group", "para_name", "local_para", "remote_para"}),
2103 : std::vector<std::string>(
2104 : {opInfo, identifier, GetInconsistentTypeStr(search->second.inconsistentType), search->second.localInfo,
2105 : search->second.remoteInfo}));
2106 0 : }
2107 0 : return HCCL_SUCCESS;
2108 0 : }
2109 :
2110 24 : HcclResult Heartbeat::SetRankPortInfo(
2111 : bool isUseRankPort, std::vector<u32>& nicRanksPorts, std::vector<u32>& vnicRanksPorts, bool devPortSwitchOn)
2112 : {
2113 24 : isUseRankPort_ = isUseRankPort;
2114 24 : nicRanksPorts_ = nicRanksPorts;
2115 24 : vnicRanksPorts_ = vnicRanksPorts;
2116 24 : devPortSwitchOn_ = devPortSwitchOn;
2117 24 : return HCCL_SUCCESS;
2118 : }
2119 :
2120 0 : void Heartbeat::SetOpretryErr()
2121 : {
2122 : // 重执行约束场景,给errStatusQueue添加重执行失败心跳帧
2123 0 : SetStatus(uid_, uid_, HeartBeatStatus::HEARTBEAT_OPRETRY_NOT_SUPPORT);
2124 0 : }
2125 :
2126 8 : u32 Heartbeat::GetPort(HcclSocketType type, u32 remoteUserRank, [[maybe_unused]] u32 remoteDeviceId)
2127 : {
2128 8 : u32 port = HCCL_INVALID_PORT;
2129 8 : if (isUseRankPort_) {
2130 0 : if (devPortSwitchOn_ && type == HcclSocketType::SOCKET_VNIC && remoteUserRank < vnicRanksPorts_.size()
2131 0 : && vnicRanksPorts_[remoteUserRank] != HCCL_INVALID_PORT) {
2132 0 : port = vnicRanksPorts_[remoteUserRank];
2133 0 : HCCL_INFO("[Heartbeat][GetPort] use vnic ranks port[%u]", port);
2134 0 : } else if (remoteUserRank < nicRanksPorts_.size() && nicRanksPorts_[remoteUserRank] != HCCL_INVALID_PORT) {
2135 0 : port = nicRanksPorts_[remoteUserRank];
2136 0 : HCCL_INFO("[Heartbeat][GetPort] use nic ranks port[%u]", port);
2137 : } else {
2138 0 : port = HETEROG_CCL_PORT;
2139 : }
2140 : } else {
2141 8 : port = HETEROG_CCL_PORT;
2142 : }
2143 8 : return port;
2144 : }
2145 :
2146 2 : u32 Heartbeat::GetHostPort(s32 devicePhyId)
2147 : {
2148 2 : if (GetExternalInputHcclIfBasePort() == HCCL_INVALID_PORT) {
2149 1 : return (devicePhyId + HOST_PARA_BASE_PORT);
2150 : } else {
2151 1 : return (devicePhyId + GetExternalInputHcclIfBasePort() + HCCL_AISERVER_DEVICE_NUM);
2152 : }
2153 : }
2154 :
2155 0 : bool Heartbeat::IsPaused() const { return !startSendRecvTask_ || isPaused_; }
2156 :
2157 0 : bool Heartbeat::IsResumed() const { return !startSendRecvTask_ || !isPaused_; }
2158 :
2159 3 : void Heartbeat::CheckSnapshotStatus()
2160 : {
2161 3 : auto snapshotStatus = SnapshotControl::GetInstance(deviceLogicId_).GetStatus();
2162 3 : if (isPaused_ && snapshotStatus == SnapshotStatus::POST_SNAPSHOT) {
2163 0 : isPaused_ = false;
2164 0 : HCCL_RUN_INFO(
2165 : "[Heartbeat][CheckSnapshotStatus] detect snapshot post-processing, heart is resumed, "
2166 : "deviceLogicId[%u].",
2167 : deviceLogicId_);
2168 3 : } else if (!isPaused_ && snapshotStatus == SnapshotStatus::PRE_SNAPSHOT) {
2169 0 : isPaused_ = true;
2170 0 : HCCL_RUN_INFO(
2171 : "[Heartbeat][CheckSnapshotStatus] detect snapshot pre-processing, heart is paused, "
2172 : "deviceLogicId[%u].",
2173 : deviceLogicId_);
2174 : }
2175 3 : }
2176 :
2177 0 : HcclResult RegisterToHeartBeat(
2178 : s32 deviceLogicID, u32 userRank, DevType devType, std::vector<RankInfo>& rankInfoList, const u32 port,
2179 : const bool isNeedNic, u32 peerRankId, const std::string& commIdentifier, const std::string& tag,
2180 : bool useSuperPodMode, bool isUsedRdmaLevel0)
2181 : {
2182 0 : return peerRankId == INVALID_VALUE_RANKID ? Heartbeat::GetInstance(deviceLogicID)
2183 0 : .RegisterToHeartBeat(
2184 : userRank, devType, rankInfoList, port, isNeedNic,
2185 : commIdentifier, useSuperPodMode, isUsedRdmaLevel0) :
2186 0 : Heartbeat::GetInstance(deviceLogicID)
2187 0 : .RegisterToHeartBeat(
2188 : userRank, devType, rankInfoList, port, isNeedNic, peerRankId,
2189 0 : commIdentifier, tag, useSuperPodMode, isUsedRdmaLevel0);
2190 : }
2191 :
2192 0 : void UnRegisterRanks(s32 deviceLogicID, DevType devType, const std::string& commIdentifier, const std::string& tag)
2193 : {
2194 0 : return tag.empty() ? Heartbeat::GetInstance(deviceLogicID).UnRegisterToHeartBeat(devType, commIdentifier) :
2195 0 : Heartbeat::GetInstance(deviceLogicID).UnRegisterToHeartBeat(devType, commIdentifier, tag);
2196 : }
2197 :
2198 0 : HcclResult SetRankPortInfo(s32 deviceLogicID, bool isUseRankPort, std::vector<u32>& ranksPort)
2199 : {
2200 0 : return Heartbeat::GetInstance(deviceLogicID).SetRankPortInfo(isUseRankPort, ranksPort, ranksPort, false);
2201 : }
2202 :
2203 17 : std::vector<std::string> GetErrStatusVec(s32 deviceLogicID, const std::string& group)
2204 : {
2205 17 : return Heartbeat::GetInstance(deviceLogicID).GetErrStatusVec(group);
2206 : }
2207 :
2208 47 : __attribute__((constructor)) void HeartBeatCallBackInit()
2209 : {
2210 47 : RegisterHeartBeatCallBack(RegisterToHeartBeat, UnRegisterRanks, SetRankPortInfo);
2211 47 : RegisterGetErrStatusVecCallBack(GetErrStatusVec);
2212 47 : }
2213 : } // namespace hccl
|