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 <mutex>
12 : #include <shared_mutex>
13 : #include <iterator>
14 : #include <functional>
15 : #include <map>
16 : #include "framework/aicpu_hccl_process.h"
17 : #include "stream_pub.h"
18 : #include "framework/aicpu_communicator.h"
19 : #include "sal_pub.h"
20 : #include "cann_error_reporter.h"
21 : #include "executor_tracer.h"
22 : #include "dfx/aicpu_executor_tracer.h"
23 : #include "framework/aicpu_one_side_service.h"
24 :
25 : namespace dfx_tracer {
26 140 : void ExecutorTracer::BackGroundDfx(void *info)
27 : {
28 140 : HCCL_RUN_INFO("Start to back ground.");
29 : // 外部保证info有效
30 140 : auto ctx = static_cast<AicpuComContext *>(info);
31 140 : hccl::HcclCommAicpu::ResetErrMsgReport(); // 业务重新拉起的场景,重置ErrMesg上报标记位
32 : while (true) {
33 : // 停止背景线程
34 8240 : if (ctx->dfxExtendInfo.commandToBackGroud == CommandToBackGroud::kStop) {
35 139 : HCCL_INFO("Back ground thread returned..");
36 139 : break;
37 : }
38 8101 : HandleDestroyComm(ctx);
39 8101 : HandleBackGround(ctx);
40 8101 : bool isNotStop = false;
41 8101 : StopBackGround(ctx, isNotStop);
42 8101 : if (!isNotStop) {
43 1 : HCCL_RUN_INFO("stop backGround Thread");
44 1 : break;
45 : }
46 8100 : HandleReportStatusInComm();
47 8100 : StopLaunchCommandHandle(ctx);
48 8100 : KfcCommandHandle(ctx);
49 8100 : HandleSwitchNic(ctx);
50 8100 : TaskMonitor();
51 8100 : HandleCqeStatus(ctx);
52 8100 : HandleResumeChangeLink(ctx);
53 8100 : hccl::HcclOneSideServiceAicpu::HandleErrCqe();
54 8100 : usleep(TEN_MILLISECOND_OF_USLEEP);
55 8100 : }
56 140 : (void)dfx::CannErrorReporter::GetInstance().Clear();
57 140 : }
58 :
59 8101 : void ExecutorTracer::HandleDestroyComm(AicpuComContext *const ctx)
60 : {
61 8101 : std::vector<std::string> destroyGroupName;
62 : {
63 8101 : std::shared_lock<std::shared_mutex> rwlock(AicpuHcclProcess::AicpuGetCommMutex());
64 8101 : std::vector<std::pair<std::string, hccl::HcclCommAicpu *>> aicpuCommInfo;
65 8101 : (void)AicpuHcclProcess::AicpuGetCommAll(aicpuCommInfo);
66 8101 : KfcCommand cmd = KfcCommand::kNone;
67 8101 : for (auto &commInfo : aicpuCommInfo) {
68 0 : hccl::HcclCommAicpu *hcclAicpu = commInfo.second;
69 0 : if (hcclAicpu->GetCommInfoStatus() || hcclAicpu->GetIsInitIndOp()) {
70 0 : (void) hcclAicpu->GetKfcCommand(cmd);
71 0 : if (cmd == KfcCommand::kDestroyComm) {
72 0 : auto groupName = hcclAicpu->GetGroupName();
73 0 : HCCL_RUN_INFO("[ExecutorTracer][%s]Recv kDestroyComm cmd, group name[%s]", __func__, groupName.c_str());
74 0 : hcclAicpu->FlushUtraceInfo();
75 0 : KfcExecStatus responseStatus;
76 0 : responseStatus.execStatus.kfcStatus = KfcStatus::kDestroyComm;
77 : // 需要在销毁通信域前返回 kfc status到host,销毁通信域会释放TransferD2H
78 0 : s32 ret = hcclAicpu->ResponseBackGroundStatus(responseStatus);
79 0 : CHK_PRT_CONT(ret, HCCL_ERROR("[ExecutorTracer][%s]ResponseBackGroundStatus failed, group[%s], ret[%d]",
80 : __func__, groupName.c_str(), ret));
81 0 : AicpuExecutorTracer::StopKfcThread(ctx, aicpuCommInfo);
82 0 : destroyGroupName.push_back(groupName);
83 0 : cmd = KfcCommand::kNone;
84 0 : }
85 : }
86 : }
87 8101 : }
88 :
89 8101 : for (auto &groupName : destroyGroupName) {
90 0 : std::unique_lock<std::shared_mutex> rwlock(AicpuHcclProcess::AicpuGetCommMutex());
91 0 : AicpuHcclProcess::AicpuDestoryCommbyGroup(groupName);
92 0 : }
93 8101 : }
94 :
95 8100 : void ExecutorTracer::TaskMonitor(void)
96 : {
97 8100 : std::shared_lock<std::shared_mutex> rwlock(AicpuHcclProcess::AicpuGetCommMutex());
98 8100 : std::vector<std::pair<std::string, hccl::HcclCommAicpu *>> aicpuCommInfo;
99 8100 : (void)AicpuHcclProcess::AicpuGetCommAll(aicpuCommInfo);
100 8100 : for (auto &commInfo : aicpuCommInfo) {
101 0 : hccl::HcclCommAicpu *hcclAicpu = commInfo.second;
102 0 : (void)hcclAicpu->StreamTaskMonitor();
103 : }
104 8100 : }
105 :
106 8101 : void ExecutorTracer::HandleBackGround(AicpuComContext *const ctx)
107 : {
108 8101 : AicpuExecutorTracer::HandleBackGround(ctx);
109 8101 : }
110 :
111 : // stop 背景线程
112 8101 : void ExecutorTracer::StopBackGround(AicpuComContext *const ctx, bool &isNotStop)
113 : {
114 8101 : if (ctx->commOpenStatus) {
115 8100 : isNotStop = true;
116 : } else {
117 1 : std::shared_lock<std::shared_mutex> rwlock(AicpuHcclProcess::AicpuGetCommMutex());
118 1 : std::vector<std::pair<std::string, hccl::HcclCommAicpu *>> aicpuCommInfo;
119 1 : (void)AicpuHcclProcess::AicpuGetCommAll(aicpuCommInfo);
120 1 : for (auto &commInfo : aicpuCommInfo) {
121 0 : hccl::HcclCommAicpu *hcclAicpu = commInfo.second;
122 0 : if (hcclAicpu->GetCommInfoStatus() || hcclAicpu->GetIsInitIndOp()) {
123 0 : isNotStop = true;
124 : }
125 : }
126 1 : }
127 :
128 8101 : if (!hccl::HcclOneSideServiceAicpu::isAllDestroy()) {
129 0 : isNotStop = true;
130 : }
131 8101 : }
132 :
133 140 : void ExecutorTracer::StopBackGroundDfx(void *info)
134 : {
135 : // 外部保证info有效
136 140 : auto ctx = static_cast<AicpuComContext *>(info);
137 140 : ctx->dfxExtendInfo.commandToBackGroud = CommandToBackGroud::kStop;
138 140 : HCCL_INFO("Stop back ground thread..");
139 140 : }
140 :
141 : // handle StopLaunch Command
142 8100 : void ExecutorTracer::StopLaunchCommandHandle(AicpuComContext *const ctx)
143 : {
144 8100 : AicpuExecutorTracer::StopLaunchCommandHandle(ctx);
145 8100 : std::shared_lock<std::shared_mutex> rwlock(AicpuHcclProcess::AicpuGetCommMutex());
146 8100 : std::vector<std::pair<std::string, hccl::HcclCommAicpu *>> aicpuCommInfo;
147 8100 : (void)AicpuHcclProcess::AicpuGetCommAll(aicpuCommInfo);
148 8100 : KfcCommand cmd = KfcCommand::kNone;
149 8100 : for (auto &commInfo : aicpuCommInfo) {
150 0 : hccl::HcclCommAicpu *hcclAicpu = commInfo.second;
151 0 : cmd = KfcCommand::kNone;
152 0 : if (hcclAicpu->GetCommInfoStatus()) {
153 0 : if (!hcclAicpu->GetNsStopLaunchStatus()) {
154 0 : (void)hcclAicpu->BackGroundGetCmd(cmd);
155 0 : if (cmd == KfcCommand::NsStopLaunch) {
156 0 : if (!hcclAicpu->BackGroundGetOpStatus()) {
157 0 : (void)hcclAicpu->BackGroundSetStatus(KfcStatus::kStoplaunch);
158 0 : hcclAicpu->SetCommRecoveryFlag(true);
159 0 : hcclAicpu->SetNsStopLaunchStatus(true);
160 0 : HCCL_RUN_INFO("[NsRecovery][backGround]group[%s] send in aicpu environment",
161 : hcclAicpu->GetGroupName().c_str());
162 : }
163 : }
164 : }
165 : }
166 : }
167 8100 : }
168 :
169 : // handle StopExec and Clean Command
170 8100 : void ExecutorTracer::KfcCommandHandle(AicpuComContext *const ctx)
171 : {
172 8100 : AicpuExecutorTracer::KfcCommandHandle(ctx);
173 8100 : std::shared_lock<std::shared_mutex> rwlock(AicpuHcclProcess::AicpuGetCommMutex());
174 8100 : std::vector<std::pair<std::string, hccl::HcclCommAicpu *>> aicpuCommInfo;
175 8100 : (void)AicpuHcclProcess::AicpuGetCommAll(aicpuCommInfo);
176 8100 : for (auto &commItem : aicpuCommInfo) {
177 0 : hccl::HcclCommAicpu *commInfo = commItem.second;
178 0 : if (commInfo->GetCommInfoStatus()) {
179 0 : if (commInfo->GetCommRecoveryFlag()) {
180 0 : HandleAICPUCommand(commInfo);
181 : }
182 : }
183 : }
184 8100 : }
185 :
186 : // handle switch nic command
187 8100 : void ExecutorTracer::HandleSwitchNic(AicpuComContext *const ctx)
188 : {
189 8100 : std::shared_lock<std::shared_mutex> rwlock(AicpuHcclProcess::AicpuGetCommMutex());
190 8100 : std::vector<std::pair<std::string, hccl::HcclCommAicpu *>> aicpuCommInfo;
191 8100 : (void)AicpuHcclProcess::AicpuGetCommAll(aicpuCommInfo);
192 8100 : for (auto &commItem : aicpuCommInfo) {
193 0 : hccl::HcclCommAicpu *hcclAicpu = commItem.second;
194 0 : if (hcclAicpu->GetCommInfoStatus()) {
195 0 : KfcCommand kfcCmd = KfcCommand::kNone;
196 0 : (void) hcclAicpu->BackGroundGetCmd(kfcCmd);
197 0 : if (kfcCmd == KfcCommand::kSwitchNic) {
198 0 : auto groupName = hcclAicpu->GetGroupName();
199 0 : HCCL_RUN_INFO("[ExecutorTracer][%s]group name[%s], aicpu start switch nic",
200 : __func__, groupName.c_str());
201 0 : HcclResult ret = hcclAicpu->SwitchNic();
202 :
203 0 : KfcExecStatus switchResp;
204 0 : if (ret == HCCL_SUCCESS) {
205 0 : switchResp.execStatus.kfcStatus = KfcStatus::kSwitchSuccess;
206 0 : (void) hcclAicpu->ResponseBackGroundStatus(switchResp);
207 : } else {
208 0 : switchResp.execStatus.kfcStatus = KfcStatus::kSwitchFail;
209 0 : (void) hcclAicpu->ResponseBackGroundStatus(switchResp);
210 : }
211 0 : HCCL_INFO("[ExecutorTracer][%s]group name[%s], aicpu finish switch nic, ret[%u]",
212 : __func__, groupName.c_str(), ret);
213 0 : }
214 : }
215 : }
216 8100 : }
217 :
218 8100 : void ExecutorTracer::HandleResumeChangeLink(AicpuComContext *const ctx)
219 : {
220 8100 : std::shared_lock<std::shared_mutex> rwlock(AicpuHcclProcess::AicpuGetCommMutex());
221 8100 : std::vector<std::pair<std::string, hccl::HcclCommAicpu *>> aicpuCommInfo;
222 8100 : (void)AicpuHcclProcess::AicpuGetCommAll(aicpuCommInfo);
223 8100 : for (auto &commItem : aicpuCommInfo) {
224 0 : hccl::HcclCommAicpu *hcclAicpu = commItem.second;
225 0 : if (hcclAicpu == nullptr) {
226 0 : HCCL_ERROR("[ExecutorTracer][%s]hcclAicpu is nullptr", __func__);
227 : }
228 0 : if (hcclAicpu != nullptr && hcclAicpu->GetCommInfoStatus()) {
229 0 : KfcCommand kfcCmd = KfcCommand::kNone;
230 0 : (void) hcclAicpu->BackGroundGetCmd(kfcCmd);
231 0 : if (kfcCmd == KfcCommand::NsChangeLink) {
232 0 : auto groupName = hcclAicpu->GetGroupName();
233 0 : HCCL_INFO("[ExecutorTracer][resume][%s]group name[%s], resume aicpu, start change link",
234 : __func__, groupName.c_str());
235 0 : HcclResult ret = hcclAicpu->ResumeChangeLink();
236 0 : KfcExecStatus resumeResp;
237 0 : if (ret == HCCL_SUCCESS) {
238 0 : resumeResp.execStatus.kfcStatus = KfcStatus::kResumeChanged;
239 0 : HCCL_INFO("[ExecutorTracer][resume][%s]group name[%s], resume aicpu, change link, kResumeChanged",__func__, groupName.c_str());
240 : } else {
241 0 : resumeResp.execStatus.kfcStatus = KfcStatus::kResumeError;
242 0 : HCCL_INFO("[ExecutorTracer][resume][%s]group name[%s], resume aicpu, change link, kResumeError",__func__, groupName.c_str());
243 : }
244 0 : (void) hcclAicpu->ResponseBackGroundStatus(resumeResp);
245 0 : HCCL_INFO("[ExecutorTracer][%s]group name[%s], resume process, finish change link, ret[%u]",
246 : __func__, groupName.c_str(), ret);
247 0 : }
248 : }
249 : }
250 8100 : }
251 :
252 8100 : void ExecutorTracer::HandleCqeStatusInComm()
253 : {
254 8100 : std::shared_lock<std::shared_mutex> rwlock(AicpuHcclProcess::AicpuGetCommMutex());
255 8100 : std::vector<std::pair<std::string, hccl::HcclCommAicpu *>> aicpuCommInfo;
256 8100 : (void)AicpuHcclProcess::AicpuGetCommAll(aicpuCommInfo);
257 :
258 8100 : for (auto &commInfo : aicpuCommInfo) {
259 0 : std::vector<hccl::Stream> streams;
260 0 : hccl::HcclCommAicpu *hcclAicpu = commInfo.second;
261 :
262 : // 通信域走自定义算子流程初始化,需要轮询thread状态
263 0 : if (hcclAicpu->GetIsInitIndOp()) {
264 0 : hcclAicpu->HandleIndOpCqe();
265 : }
266 :
267 0 : if (!hcclAicpu->GetCommInfoStatus()) { // 已结束, 不再轮询
268 0 : continue;
269 : }
270 0 : DfxExtendInfo* dfxInfo = hcclAicpu->GetDfxExtendInfo();
271 0 : if ((dfxInfo->cqeStatus != dfx::CqeStatus::kDefault) && (dfxInfo->cqeStatus != dfx::CqeStatus::kCqeException)) {
272 0 : continue;
273 : }
274 :
275 0 : (void)hcclAicpu->GetStreamAll(streams);
276 0 : for (hccl::Stream &stream : streams) {
277 0 : hcclAicpu->HandleCqeException(stream, false);
278 : }
279 0 : }
280 8100 : }
281 :
282 8100 : void ExecutorTracer::HandleReportStatusInComm()
283 : {
284 8100 : std::shared_lock<std::shared_mutex> rwlock(AicpuHcclProcess::AicpuGetCommMutex());
285 8100 : std::vector<std::pair<std::string, hccl::HcclCommAicpu *>> aicpuCommInfo;
286 8100 : (void)AicpuHcclProcess::AicpuGetCommAll(aicpuCommInfo);
287 :
288 8100 : for (auto &commInfo : aicpuCommInfo) {
289 0 : hccl::HcclCommAicpu *hcclAicpu = commInfo.second;
290 :
291 0 : if (!hcclAicpu || !hcclAicpu->GetCommInfoStatus()) { // 已结束, 不再轮询
292 0 : continue;
293 : }
294 :
295 0 : u32 deviceId = hcclAicpu->GetDevId();
296 :
297 0 : std::queue<dfx::ReportStatus> reportStatusQueue;
298 0 : (void)hcclAicpu->GetReportStatusQueue(reportStatusQueue);
299 :
300 0 : while (!reportStatusQueue.empty()) {
301 0 : dfx::ReportStatus reportStatus = reportStatusQueue.front();
302 0 : HCCL_INFO("Reporting opRetry status[%u] to dp frame, deviceId[%u], report queue size[%u].",
303 : reportStatus, deviceId, reportStatusQueue.size());
304 0 : HcclResult ret = dfx::CannErrorReporter::GetInstance().UpdateSensorNode(deviceId, reportStatus);
305 0 : if (ret != HCCL_SUCCESS) {
306 0 : HCCL_WARNING("Fail to report reportStatus[%u] to dp frame, status dropped, deviceId[%u].",
307 : reportStatus, deviceId);
308 : }
309 0 : reportStatusQueue.pop();
310 : }
311 0 : }
312 8100 : }
313 :
314 8100 : void ExecutorTracer::HandleCqeStatus(AicpuComContext *const ctx)
315 : {
316 8100 : HandleCqeStatusInComm();
317 8100 : AicpuExecutorTracer::HandleCqeStatus(ctx);
318 8100 : }
319 :
320 0 : void ExecutorTracer::SetCqeQueryInput(const uint32_t devId, const HcclComStreamInfo &streamInfo,
321 : CqeQueryInput &cqeQueryInput)
322 : {
323 0 : cqeQueryInput.devId = devId;
324 0 : cqeQueryInput.streamId = streamInfo.actualStreamId;
325 0 : cqeQueryInput.sqId = streamInfo.sqId;
326 0 : cqeQueryInput.cqId = streamInfo.logicCqId;
327 0 : cqeQueryInput.type = static_cast<uint32_t>(DRV_LOGIC_TYPE);
328 0 : }
329 :
330 0 : void ExecutorTracer::HandleAICPUCommand(hccl::HcclCommAicpu *const commInfo){
331 : using CommandCall = std::function<void(hccl::HcclCommAicpu *const commInfo)>;
332 : static std::map<KfcCommand, CommandCall> commandAicpuHandles = {
333 0 : {KfcCommand::NsStopExec, AICPUcommandHandles::NsCommStop},
334 0 : {KfcCommand::NsClear, AICPUcommandHandles::NsCommClean}};
335 0 : KfcCommand cmd = KfcCommand::kNone;
336 0 : (void) commInfo->BackGroundGetCmd(cmd);
337 0 : auto iter = commandAicpuHandles.find(cmd);
338 0 : if (iter == commandAicpuHandles.cend()) {
339 0 : return;
340 : }
341 0 : HCCL_RUN_INFO("Group[%s] start to run aicpu command %ld", commInfo->GetGroupName().c_str(), cmd);
342 0 : iter->second(commInfo);
343 0 : }
344 :
345 0 : void AICPUcommandHandles::NsCommStop(hccl::HcclCommAicpu *const commInfo)
346 : {
347 0 : bool streamStatus = commInfo->GetCommInfoStreamStatus();
348 0 : if (streamStatus) {
349 0 : std::string groupName = commInfo->GetGroupName();
350 0 : commInfo->SetCommInfoStreamStatus(false);
351 0 : HCCL_RUN_INFO("[NsRecovery][NsCommStop] groupName[%s]", groupName.c_str());
352 0 : commInfo->NsCommStop();
353 0 : }
354 0 : }
355 :
356 0 : void AICPUcommandHandles::NsCommClean(hccl::HcclCommAicpu *const commInfo){
357 0 : bool streamStatus = commInfo->GetCommInfoStreamStatus();
358 0 : if (!streamStatus) {
359 0 : std::string groupName = commInfo->GetGroupName();
360 0 : commInfo->SetCommInfoStreamStatus(true);
361 0 : HCCL_RUN_INFO("[NsRecovery][NsCommClean] groupName[%s]", groupName.c_str());
362 0 : commInfo->NsCommClean();
363 0 : commInfo->SetCommRecoveryFlag(false);
364 0 : }
365 0 : }
366 : } // namespace dfx_tracer
|