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 "aicpusd_interface_process.h"
12 : #include <securec.h>
13 : #include <unistd.h>
14 : #include "aicpusd_info.h"
15 : #include "ascend_hal.h"
16 : #include "aicpusd_event_manager.h"
17 : #include "aicpusd_event_process.h"
18 : #include "aicpusd_threads_process.h"
19 : #include "dump_task.h"
20 : #include "ts_api.h"
21 : #include "aicpu_context.h"
22 : #include "aicpusd_common.h"
23 : #include "aicpusd_context.h"
24 : #include "aicpusd_util.h"
25 : #include "aicpu_sched/common/aicpu_task_struct.h"
26 : #include "aicpusd_resource_manager.h"
27 : #include "aicpusd_drv_manager.h"
28 : #include "aicpusd_model_execute.h"
29 : #include "aicpu_engine.h"
30 : #include "aicpusd_profiler.h"
31 : #include "aicpusd_monitor.h"
32 : #include "aicpusd_msg_send.h"
33 : #include "aicpusd_worker.h"
34 : #include "aicpusd_cust_so_manager.h"
35 : #include "aicpusd_sub_module_interface.h"
36 : #include "aicpusd_hal_interface_ref.h"
37 : #include "aicpusd_cust_dump_process.h"
38 : #include "aicpusd_mc2_maintenance_thread.h"
39 : #include "aicpusd_period_statistic.h"
40 : #include "aicpusd_model_statistic.h"
41 : #include "aicpusd_feature_ctrl.h"
42 : #include "aicpusd_msq_operator_manager.h"
43 : #include "hwts_kernel_register.h"
44 : #include "operator_kernel_register.h"
45 :
46 : namespace {
47 : const std::map<EVENT_ID, SCHEDULE_PRIORITY> EVENT_PRIORITY = {
48 : {EVENT_ID::EVENT_RANDOM_KERNEL, SCHEDULE_PRIORITY::PRIORITY_LEVEL0},
49 : {EVENT_ID::EVENT_SPLIT_KERNEL, SCHEDULE_PRIORITY::PRIORITY_LEVEL0},
50 : {EVENT_ID::EVENT_DVPP_MSG, SCHEDULE_PRIORITY::PRIORITY_LEVEL0},
51 : {EVENT_ID::EVENT_DVPP_MPI_MSG, SCHEDULE_PRIORITY::PRIORITY_LEVEL0},
52 : {EVENT_ID::EVENT_FR_MSG, SCHEDULE_PRIORITY::PRIORITY_LEVEL0},
53 : {EVENT_ID::EVENT_TS_HWTS_KERNEL, SCHEDULE_PRIORITY::PRIORITY_LEVEL0},
54 : {EVENT_ID::EVENT_AICPU_MSG, SCHEDULE_PRIORITY::PRIORITY_LEVEL0},
55 : {EVENT_ID::EVENT_TS_CTRL_MSG, SCHEDULE_PRIORITY::PRIORITY_LEVEL0},
56 : {EVENT_ID::EVENT_FFTS_PLUS_MSG, SCHEDULE_PRIORITY::PRIORITY_LEVEL0},
57 : {EVENT_ID::EVENT_QUEUE_EMPTY_TO_NOT_EMPTY, SCHEDULE_PRIORITY::PRIORITY_LEVEL0},
58 : {EVENT_ID::EVENT_QUEUE_FULL_TO_NOT_FULL, SCHEDULE_PRIORITY::PRIORITY_LEVEL0},
59 : {EVENT_ID::EVENT_TDT_ENQUEUE, SCHEDULE_PRIORITY::PRIORITY_LEVEL2},
60 : {EVENT_ID::EVENT_ACPU_MSG_TYPE1, SCHEDULE_PRIORITY::PRIORITY_LEVEL1}
61 : };
62 :
63 : // first array index
64 : constexpr size_t FIRST_INDEX = 0LU;
65 :
66 : // max number of eatch device can split
67 : constexpr const uint32_t DEVICE_MAX_SPLIT_NUM = 16U;
68 :
69 : constexpr uint32_t MAX_AICPU_PROC_NUM = 48U;
70 :
71 : const std::string TSKERNEL_PREFIX = "tsKernel:";
72 : }
73 : namespace AicpuSchedule {
74 : /**
75 : * @ingroup AicpuScheduleCore
76 : * @brief it is used to construct a object of AicpuScheduleCore.
77 : */
78 2 : AicpuScheduleInterface::AicpuScheduleInterface()
79 2 : : profilingMode_(PROFILING_CLOSE),
80 2 : noThreadFlag_(true),
81 2 : initFlag_(false),
82 2 : eventBitMap_(0U),
83 2 : runMode_(aicpu::AicpuRunMode::THREAD_MODE),
84 2 : aicpuCustSdPid_(-1),
85 2 : isNeedBatchLoadSo_(true) {}
86 :
87 : /**
88 : * @ingroup AicpuScheduleCore
89 : * @brief it is used to destructor a object of AicpuScheduleCore.
90 : */
91 2 : AicpuScheduleInterface::~AicpuScheduleInterface() {}
92 :
93 213 : AicpuScheduleInterface &AicpuScheduleInterface::GetInstance()
94 : {
95 213 : static AicpuScheduleInterface instance;
96 213 : return instance;
97 : }
98 :
99 6 : int32_t AicpuScheduleInterface::LoadModelWithQueue(const void * const ptr) const
100 : {
101 6 : std::vector<QueInfo> queInfos;
102 6 : std::vector<AicpuTaskInfo> aicpuTaskInfos;
103 6 : std::vector<StreamInfo> streamInfos;
104 : AicpuModelInfo curAicpuModelInfo;
105 :
106 6 : if (ptr == nullptr) {
107 1 : aicpusd_err("the parameter is not valid in load model.");
108 1 : return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
109 : }
110 :
111 5 : const auto ret = AicpuModelManager::GetInstance().TransModelInfo(ptr, curAicpuModelInfo,
112 : aicpuTaskInfos, streamInfos, queInfos, nullptr);
113 5 : if (ret != AICPU_SCHEDULE_OK) {
114 2 : return ret;
115 : }
116 :
117 3 : if (queInfos.empty()) {
118 1 : return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
119 : }
120 2 : return LoadProcess(&curAicpuModelInfo);
121 6 : }
122 :
123 0 : int32_t AicpuScheduleInterface::LoadModelWithEvent(const void * const ptr) const
124 : {
125 0 : std::vector<QueInfo> queInfos;
126 0 : std::vector<AicpuTaskInfo> aicpuTaskInfos;
127 0 : std::vector<StreamInfo> streamInfos;
128 0 : std::vector<ModelCfgInfo> modelCfgs;
129 : AicpuModelInfo curAicpuModelInfo;
130 :
131 0 : if (ptr == nullptr) {
132 0 : aicpusd_err("the parameter is not valid in load model.");
133 0 : return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
134 : }
135 :
136 0 : const auto ret = AicpuModelManager::GetInstance().TransModelInfo(ptr, curAicpuModelInfo,
137 : aicpuTaskInfos, streamInfos, queInfos, &modelCfgs);
138 0 : if (ret != AICPU_SCHEDULE_OK) {
139 0 : return ret;
140 : }
141 :
142 0 : if (modelCfgs.empty()) {
143 0 : aicpusd_err("Invalid modelCfg");
144 0 : return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
145 : }
146 0 : return LoadProcess(&curAicpuModelInfo, &modelCfgs[0U]);
147 0 : }
148 :
149 : /**
150 : * @ingroup AicpuScheduleInterface
151 : * @brief it use to load the task and stream info.
152 : * @param [in] ptr : the address of the task and stream info
153 : * @return AICPU_SCHEDULE_OK: success
154 : */
155 12 : int32_t AicpuScheduleInterface::LoadProcess(const void * const ptr, const ModelCfgInfo * const cfg) const
156 : {
157 12 : if (ptr == nullptr) {
158 1 : aicpusd_err("the parameter is not valid in load model.");
159 1 : return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
160 : }
161 :
162 11 : const AicpuModelInfo * const infoTask = PtrToPtr<const void, const AicpuModelInfo>(ptr);
163 11 : const uint32_t modelId = infoTask->moduleID;
164 11 : aicpusd_info("Begin to load model[%u]", modelId);
165 11 : const int32_t ret = AicpuModelManager::GetInstance().ModelLoad(infoTask, cfg);
166 11 : if (ret != AICPU_SCHEDULE_OK) {
167 2 : aicpusd_err("Failed to load model[%u].", modelId);
168 2 : return ret;
169 : }
170 :
171 9 : aicpusd_info("Model[%u] queue size[%u]", modelId, infoTask->queueSize);
172 9 : if (static_cast<int32_t>(infoTask->queueSize) > 0) {
173 0 : AicpuEventProcess::GetInstance().InitQueueFlag();
174 0 : return ExecuteModelAsync(modelId);
175 : }
176 :
177 9 : if (cfg != nullptr) {
178 0 : return ExecuteModelAsync(modelId);
179 : }
180 9 : return AICPU_SCHEDULE_OK;
181 : }
182 :
183 : /**
184 : * @ingroup AicpuScheduleInterface
185 : * @brief it use to execute model.
186 : * @param [in] modelId : modelId
187 : * @return AICPU_SCHEDULE_OK: success
188 : */
189 0 : int32_t AicpuScheduleInterface::ExecuteModelAsync(const uint32_t modelId) const
190 : {
191 0 : aicpusd_info("Begin to execute model[%u] async", modelId);
192 0 : AICPUSubEventInfo subEventInfo = {};
193 0 : subEventInfo.modelId = modelId;
194 0 : const bool syncSendFlag = GetCpuMode();
195 0 : return AicpuMsgSend::SendAICPUSubEvent(PtrToPtr<AICPUSubEventInfo, const char_t>(&subEventInfo),
196 : static_cast<uint32_t>(sizeof(AICPUSubEventInfo)),
197 : AICPU_SUB_EVENT_EXECUTE_MODEL,
198 : CP_DEFAULT_GROUP_ID,
199 0 : syncSendFlag);
200 : }
201 :
202 : /**
203 : * @ingroup AicpuScheduleInterface
204 : * @brief it use to get the errorcode for external module by the model status.
205 : * @param [in] modelId : modelId
206 : * @return AICPU_SCHEDULE_SUCCESS: success, other: error code
207 : */
208 7 : ErrorCode AicpuScheduleInterface::GetErrorCode(const uint32_t modelId) const
209 : {
210 7 : const AicpuModelStatus status = AicpuModelManager::GetInstance().GetModelStatus(modelId);
211 7 : if (status == AicpuModelStatus::MODEL_STATUS_ERROR) {
212 0 : return AICPU_SCHEDULE_FAIL;
213 7 : } else if (status == AicpuModelStatus::MODEL_STATUS_ABORT) {
214 0 : return AICPU_SCHEDULE_ABORT;
215 : } else {
216 7 : return AICPU_SCHEDULE_SUCCESS;
217 : }
218 : }
219 :
220 : /**
221 : * @ingroup AicpuScheduleInterface
222 : * @brief it use to send message to tscpu.
223 : * @param [in] deviceId
224 : */
225 6 : void AicpuScheduleInterface::SendMsgToTsCpu(const uint32_t deviceId) const
226 : {
227 : // send msg to tscpu
228 6 : AicpuSqeAdapter aicpuadapter(FeatureCtrl::GetTsMsgVersion());
229 6 : const int32_t ret = aicpuadapter.AicpuNoticeTsPidResponse(deviceId);
230 6 : if (ret != AICPU_SCHEDULE_OK) {
231 1 : aicpusd_run_warn("AicpuNoticeTsPidResponse ret:%d.", ret);
232 : }
233 6 : }
234 :
235 6 : int32_t AicpuScheduleInterface::BindHostPid(const std::string &pidSign, const uint32_t vfId) const
236 : {
237 6 : int32_t ret = 0;
238 6 : if (runMode_ == aicpu::AicpuRunMode::THREAD_MODE) {
239 1 : constexpr int32_t mode = static_cast<int32_t>(AicpuPlat::AICPU_OFFLINE_PLAT);
240 1 : ret = AicpuDrvManager::GetInstance().BindHostPid(pidSign, mode,
241 : vfId, DEVDRV_PROCESS_CP1);
242 1 : int32_t getRet = 0;
243 1 : getRet = AicpuDrvManager::GetInstance().BindHostPid(pidSign, mode,
244 : vfId, DEVDRV_PROCESS_CP2);
245 1 : aicpusd_warn("BindHostPid DEVDRV_PROCESS_CP2 ret[%d]", getRet);
246 : } else {
247 5 : ret = AicpuDrvManager::GetInstance().CheckBindHostPid();
248 : }
249 6 : return ret;
250 : }
251 :
252 : /**
253 : * @ingroup AicpuScheduleInterface
254 : * @brief it use to initialize aicpu schedule.
255 : * @param [in] deviceId
256 : * @param [in] hostPid : the process id of host
257 : * @param [in] pidSign : the signature of pid ,it is used in drv.
258 : * @param [in] profilingMode
259 : * @param [in] vfId : vf id
260 : * @param [in] isOnline: true-process mode; false-thread mode
261 : * @return AICPU_SCHEDULE_OK: success, other: error code
262 : */
263 14 : int32_t AicpuScheduleInterface::InitAICPUScheduler(const std::vector<uint32_t> &deviceVec,
264 : const pid_t hostPid,
265 : const std::string &pidSign,
266 : const uint32_t profilingMode,
267 : const uint32_t vfId,
268 : const bool isOnline,
269 : const std::string &hostProcName)
270 : {
271 14 : if (deviceVec.empty()) {
272 0 : aicpusd_err("device vector is empty");
273 0 : return AICPU_SCHEDULE_ERROR_DRV_ERR;
274 : }
275 :
276 14 : if (IsInitialized(deviceVec[0])) {
277 6 : aicpusd_warn("Aicpu schedule is already init.");
278 6 : return AICPU_SCHEDULE_OK;
279 : }
280 8 : const std::unique_lock<std::mutex> lockForInit(mutexForInit_);
281 8 : UpdateOrInsertStartFlag(deviceVec[0], false);
282 8 : noThreadFlag_ = false;
283 :
284 : // get aicpu run mode
285 8 : const int32_t getRet = GetCurrentRunMode(isOnline);
286 8 : if (getRet != AICPU_SCHEDULE_OK) {
287 0 : aicpusd_err("getRet is not ok:%u", getRet);
288 0 : return getRet;
289 : }
290 8 : if (AicpuDrvManager::GetInstance().InitDrvMgr(deviceVec, hostPid, vfId,
291 8 : true, runMode_, hostProcName) != AICPU_SCHEDULE_OK) {
292 0 : aicpusd_err("Failed to init aicpu drv manager");
293 0 : return AICPU_SCHEDULE_ERROR_DRV_ERR;
294 : }
295 8 : (void)aicpu::SetAicpuRunMode(runMode_); // InitDrvSchedModule will use the runMode.
296 8 : DeployContext deployCtx = DeployContext::DEVICE;
297 8 : const StatusCode status = GetAicpuDeployContext(deployCtx);
298 8 : if (status != AICPU_SCHEDULE_OK) {
299 0 : aicpusd_err("Get current deploy ctx failed.");
300 0 : return status;
301 : }
302 8 : const bool cpuMode = GetCpuMode();
303 8 : if ((deployCtx == DeployContext::DEVICE) && (!cpuMode)) {
304 6 : const int32_t bindPidRet = BindHostPid(pidSign, vfId);
305 6 : if (bindPidRet != AICPU_SCHEDULE_OK) {
306 0 : aicpusd_err("check bind pid sign failed, ret[%d].", bindPidRet);
307 0 : return bindPidRet;
308 : }
309 6 : aicpusd_info("Bind pid sign success");
310 : }
311 :
312 8 : constexpr uint32_t groupId = CP_DEFAULT_GROUP_ID;
313 8 : int32_t ret = AicpuDrvManager::GetInstance().InitDrvSchedModule(groupId, EVENT_PRIORITY);
314 8 : if (ret != DRV_ERROR_NONE) {
315 1 : aicpusd_err("Failed to init the drv schedule module, ret[%d].", ret);
316 1 : return AICPU_SCHEDULE_ERROR_DRV_ERR;
317 : }
318 7 : ret = AicpuSchedule::AicpuMonitor::GetInstance().InitMonitor(deviceVec[FIRST_INDEX], isOnline);
319 7 : if (ret != AICPU_SCHEDULE_OK) {
320 0 : aicpusd_err("aicpu monitor init failed, ret[%d]", ret);
321 0 : return AICPU_SCHEDULE_ERROR_INIT_FAILED;
322 : }
323 7 : const AicpuSchedMode schedMode = FeatureCtrl::GetAicpuSchedMode();
324 7 : AicpuEventManager::GetInstance().InitEventFunc(schedMode);
325 7 : (void)AicpuSchedule::AicpuEventProcess::GetInstance(); // Pre init instance
326 7 : const auto retCp = ComputeProcess::GetInstance().Start(deviceVec, hostPid, pidSign, profilingMode,
327 : vfId, runMode_);
328 7 : if (retCp != AICPU_SCHEDULE_OK) {
329 1 : aicpusd_err("Compute process start failed, ret[%d].", retCp);
330 1 : ComputeProcess::GetInstance().Stop();
331 1 : AicpuSchedule::AicpuMonitor::GetInstance().StopMonitor();
332 1 : return AICPU_SCHEDULE_ERROR_INIT_CP_FAILED;
333 : }
334 6 : AicpuSchedule::AicpuSdPeriodStatistic::GetInstance().InitStatistic(deviceVec[FIRST_INDEX], hostPid, runMode_);
335 6 : AicpuSchedule::AicpuSdModelStatistic::GetInstance().InitModelStatInfo();
336 : // send message to tscpu, failure is not handled and does not affect the main process
337 6 : SendMsgToTsCpu(deviceVec[FIRST_INDEX]);
338 6 : const auto conRet = BuildAndSetContext(deviceVec[FIRST_INDEX], hostPid, vfId);
339 6 : if (conRet != AICPU_SCHEDULE_OK) {
340 0 : return conRet;
341 : }
342 :
343 : // init AicpuCustSoManager
344 6 : (void)AicpuSchedule::AicpuCustSoManager::GetInstance().InitAicpuCustSoManager(runMode_, schedMode);
345 6 : aicpusd_info("Successfully started compute process, deviceId[%u], hostPid[%d], runMode[%u]",
346 : deviceVec[FIRST_INDEX], hostPid, runMode_);
347 6 : UpdateOrInsertStartFlag(deviceVec[0], true);
348 6 : return AICPU_SCHEDULE_OK;
349 8 : }
350 :
351 7 : int32_t AicpuScheduleInterface::BuildAndSetContext(
352 : const uint32_t deviceId, const pid_t hostPid, const uint32_t vfId)
353 : {
354 7 : aicpu::aicpuContext_t context = {
355 : .deviceId = deviceId,
356 : .tsId = 0U,
357 : .hostPid = hostPid,
358 : .vfId = vfId
359 7 : };
360 7 : uint32_t uniqueVfId = context.vfId;
361 7 : (void)aicpu::aicpuSetContext(&context);
362 7 : aicpu::SetUniqueVfId(uniqueVfId);
363 7 : if (FeatureCtrl::IsAosCore()) {
364 1 : return AICPU_SCHEDULE_OK;
365 : }
366 6 : if (FeatureCtrl::IsVfModeCheckedByDeviceId(deviceId)) {
367 0 : uniqueVfId = deviceId;
368 : } else {
369 6 : if ((context.deviceId != 0U) && (context.vfId != 0U)) {
370 1 : uint32_t maxNumSpDev = 0U;
371 1 : const auto vfMaxRet = halGetDeviceVfMax(context.deviceId, &maxNumSpDev);
372 1 : if ((vfMaxRet != DRV_ERROR_NONE) || (maxNumSpDev > DEVICE_MAX_SPLIT_NUM)) {
373 0 : aicpusd_err("Failed to get device cat vf number, result[%d], max num[%u].", vfMaxRet, maxNumSpDev);
374 0 : ComputeProcess::GetInstance().Stop();
375 0 : AicpuSchedule::AicpuMonitor::GetInstance().StopMonitor();
376 0 : return AICPU_SCHEDULE_ERROR_INIT_CP_FAILED;
377 : } else {
378 1 : uniqueVfId = (maxNumSpDev * context.deviceId) + context.vfId;
379 : }
380 : }
381 : }
382 6 : aicpu::SetUniqueVfId(uniqueVfId);
383 6 : return AICPU_SCHEDULE_OK;
384 : }
385 :
386 : /**
387 : * @ingroup AicpuScheduleInterface
388 : * @param [in] modelId
389 : * @brief it use to destroy one model.
390 : * @return AICPU_SCHEDULE_OK: success, other: error code
391 : */
392 10 : int32_t AicpuScheduleInterface::Destroy(const uint32_t modelId) const
393 : {
394 10 : const auto model = AicpuModelManager::GetInstance().GetModel(modelId);
395 10 : if (model == nullptr) {
396 1 : aicpusd_err("Model[%u] is not found.", modelId);
397 1 : return AICPU_SCHEDULE_ERROR_MODEL_NOT_FOUND;
398 : }
399 :
400 9 : const uint32_t tsId = model->GetModelTsId();
401 9 : if (tsId < static_cast<uint32_t>(TSIDFlag::AICPU_SCHEDULE_TS_ID)) {
402 1 : TsAicpuSqe tsAicpuSqe = {};
403 1 : tsAicpuSqe.pid = static_cast<uint32_t>(AicpuDrvManager::GetInstance().GetHostPid());
404 1 : tsAicpuSqe.cmd_type = AICPU_MODEL_OPERATE;
405 1 : tsAicpuSqe.vf_id = static_cast<uint8_t>(AicpuDrvManager::GetInstance().GetVfId());
406 1 : tsAicpuSqe.tid = static_cast<uint8_t>(0U); // no need tid
407 1 : tsAicpuSqe.ts_id = static_cast<uint8_t>(tsId);
408 1 : tsAicpuSqe.u.aicpu_model_operate.cmd_type = TS_AICPU_MODEL_DESTROY;
409 1 : tsAicpuSqe.u.aicpu_model_operate.model_id = static_cast<uint16_t>(modelId);
410 1 : tsAicpuSqe.u.aicpu_model_operate.arg_ptr = 0UL;
411 1 : tsAicpuSqe.u.aicpu_model_operate.task_id = static_cast<uint16_t>(0U);
412 :
413 1 : const int32_t drvRet = tsDevSendMsgAsync(AicpuDrvManager::GetInstance().GetDeviceId(), tsId,
414 : PtrToPtr<TsAicpuSqe, char_t>(&tsAicpuSqe),
415 : static_cast<uint32_t>(sizeof(TsAicpuSqe)), modelId);
416 1 : if (drvRet != DRV_ERROR_NONE) {
417 0 : aicpusd_err("Failed to send destroy model[%u] to ts[%u] , result[%d].", modelId, tsId, drvRet);
418 : }
419 1 : aicpusd_info("Successfully destroyed tsDevSendMsgAsync.");
420 : }
421 :
422 9 : const auto ret = model->ModelDestroy();
423 9 : AicpuModelManager::GetInstance().ModelConfigClear(modelId);
424 9 : return ret;
425 : }
426 :
427 : /**
428 : * @ingroup AicpuScheduleInterface
429 : * @param [in] modelId
430 : * @brief it use to stop one model.
431 : * @return AICPU_SCHEDULE_OK: success, other: error code
432 : */
433 3 : int32_t AicpuScheduleInterface::Stop(const uint32_t modelId) const
434 : {
435 3 : const auto model = AicpuModelManager::GetInstance().GetModel(modelId);
436 3 : if (model == nullptr) {
437 1 : aicpusd_err("Model[%u] is not found.", modelId);
438 1 : return AICPU_SCHEDULE_ERROR_MODEL_NOT_FOUND;
439 : }
440 :
441 2 : const uint32_t tsId = model->GetModelTsId();
442 2 : if (tsId < static_cast<uint32_t>(TSIDFlag::AICPU_SCHEDULE_TS_ID)) {
443 1 : TsAicpuSqe tsAicpuSqe = {};
444 1 : tsAicpuSqe.pid = static_cast<uint32_t>(AicpuDrvManager::GetInstance().GetHostPid());
445 1 : tsAicpuSqe.cmd_type = AICPU_MODEL_OPERATE;
446 1 : tsAicpuSqe.vf_id = static_cast<uint8_t>(AicpuDrvManager::GetInstance().GetVfId());
447 1 : tsAicpuSqe.tid = static_cast<uint8_t>(0U); // no need tid
448 1 : tsAicpuSqe.ts_id = static_cast<uint8_t>(tsId);
449 1 : tsAicpuSqe.u.aicpu_model_operate.cmd_type = TS_AICPU_MODEL_DESTROY;
450 1 : tsAicpuSqe.u.aicpu_model_operate.model_id = static_cast<uint16_t>(modelId);
451 1 : tsAicpuSqe.u.aicpu_model_operate.arg_ptr = 0UL;
452 1 : tsAicpuSqe.u.aicpu_model_operate.task_id = static_cast<uint16_t>(0U);
453 :
454 1 : const int32_t drvRet = tsDevSendMsgAsync(AicpuDrvManager::GetInstance().GetDeviceId(), tsId,
455 : PtrToPtr<TsAicpuSqe, char_t>(&tsAicpuSqe),
456 : static_cast<uint32_t>(sizeof(TsAicpuSqe)), modelId);
457 1 : if (drvRet != DRV_ERROR_NONE) {
458 1 : aicpusd_err("Failed to send destroy model[%u] to ts[%u] , result[%d].", modelId, tsId, drvRet);
459 : }
460 1 : aicpusd_info("Successfully destroyed tsDevSendMsgAsync.");
461 : }
462 :
463 2 : uint32_t retryCost = 0U;
464 2 : const uint32_t retryIntervalUs = 10000U;
465 2 : const uint32_t retryCostLimitUs = 1000000U;
466 2 : auto stopRet = model->ModelStop();
467 2 : while ((stopRet == AICPU_SCHEDULE_ERROR_IN_WORKING) && (retryCost < retryCostLimitUs)) {
468 0 : usleep(retryIntervalUs);
469 0 : retryCost += retryIntervalUs;
470 0 : stopRet = model->ModelStop();
471 : }
472 2 : aicpusd_run_info("Stop model[%u], ret is %d, retryCost is %u.", modelId, stopRet, retryCost);
473 2 : return stopRet;
474 : }
475 :
476 2 : int32_t AicpuScheduleInterface::Restart(const uint32_t modelId) const
477 : {
478 2 : const auto model = AicpuModelManager::GetInstance().GetModel(modelId);
479 2 : if (model == nullptr) {
480 1 : aicpusd_err("Model[%u] is not found.", modelId);
481 1 : return AICPU_SCHEDULE_ERROR_MODEL_NOT_FOUND;
482 : }
483 :
484 1 : uint32_t retryCost = 0U;
485 1 : const uint32_t retryIntervalUs = 10000U;
486 1 : const uint32_t retryCostLimitUs = 1000000U;
487 1 : auto restartRet = model->ModelRestart();
488 1 : while ((restartRet == AICPU_SCHEDULE_ERROR_IN_WORKING) && (retryCost < retryCostLimitUs)) {
489 0 : usleep(retryIntervalUs);
490 0 : retryCost += retryIntervalUs;
491 0 : restartRet = model->ModelRestart();
492 : }
493 1 : aicpusd_run_info("Restart model[%u], ret is %d, retryCost is %u.", modelId, restartRet, retryCost);
494 1 : return restartRet;
495 : }
496 :
497 6 : int32_t AicpuScheduleInterface::CheckKernelSupported(const std::string &kernelName) const
498 : {
499 6 : const auto pos = kernelName.find(TSKERNEL_PREFIX);
500 6 : if (pos != kernelName.npos) {
501 2 : const std::string tsKernelName = kernelName.substr(TSKERNEL_PREFIX.length());
502 2 : return HwTsKernelRegister::Instance().CheckTsKernelSupported(tsKernelName);
503 2 : }
504 4 : return OperatorKernelRegister::Instance().CheckOperatorKernelSupported(kernelName);
505 : }
506 :
507 2 : int32_t AicpuScheduleInterface::ClearInput(const uint32_t modelId) const
508 : {
509 2 : const auto model = AicpuModelManager::GetInstance().GetModel(modelId);
510 2 : if (model == nullptr) {
511 1 : aicpusd_err("Model[%u] is not found.", modelId);
512 1 : return AICPU_SCHEDULE_ERROR_MODEL_NOT_FOUND;
513 : }
514 :
515 1 : return model->ModelClearInput();
516 : }
517 :
518 : /**
519 : * @ingroup AicpuScheduleInterface
520 : * @brief it use to destroy all model.
521 : */
522 24 : int32_t AicpuScheduleInterface::Destroy() const
523 : {
524 24 : if (AicpuModelManager::IsUsed()) {
525 21 : return AicpuModelManager::GetInstance().Exit();
526 : }
527 3 : return AICPU_SCHEDULE_OK;
528 : }
529 :
530 : /**
531 : * @ingroup AicpuScheduleInterface
532 : * @brief it use to stop AICPU scheduler.
533 : * @param [in] deviceId
534 : * @param [in] hostPid :the process id of host
535 : * @return AICPU_SCHEDULE_OK: success, other: error code
536 : */
537 23 : int32_t AicpuScheduleInterface::StopAICPUScheduler(const std::vector<uint32_t> &deviceVec, const pid_t hostPid)
538 : {
539 23 : return StopAICPUSchedulerWithFlag(deviceVec, hostPid, false);
540 : }
541 :
542 24 : int32_t AicpuScheduleInterface::StopAICPUSchedulerWithFlag(const std::vector<uint32_t> &deviceVec,
543 : const pid_t hostPid, const bool waitThreadStop)
544 : {
545 24 : if (deviceVec.empty()) {
546 0 : aicpusd_err("deviceVec is empty.");
547 0 : return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
548 : }
549 24 : aicpusd_run_info("Begin to stop aicpu scheduler, hostPid[%d]", hostPid);
550 24 : const std::unique_lock<std::mutex> lockForInit(mutexForInit_);
551 24 : if (!noThreadFlag_) {
552 5 : ComputeProcess::GetInstance().Stop();
553 : }
554 :
555 24 : (void)Destroy();
556 24 : noThreadFlag_ = true;
557 24 : UpdateOrInsertStartFlag(deviceVec[0], false);
558 24 : AicpuSchedule::DumpSessionManager::GetInstance().CloseAllSessions();
559 24 : AicpuSchedule::AicpuMonitor::GetInstance().StopMonitor();
560 24 : AicpuSchedule::AicpuEventManager::GetInstance().SetRunningFlag(false);
561 24 : AicpuSchedule::AicpuSdPeriodStatistic::GetInstance().StopStatistic();
562 24 : AicpuSchedule::AicpuSdPeriodStatistic::GetInstance().PrintOutStatisticInfo(runMode_);
563 24 : AicpuSchedule::AicpuSdModelStatistic::GetInstance().PrintOutModelStatInfo();
564 24 : AicpuSchedule::AicpuMc2MaintenanceThread::GetInstance(0).UnitMc2MantenanceProcess();
565 24 : AicpuSchedule::AicpuMc2MaintenanceThread::GetInstance(1).UnitMc2MantenanceProcess();
566 24 : AicpuSchedule::AicpuSdCustDumpProcess::GetInstance().UnitCustDataDumpProcess();
567 24 : FeatureCtrl::ClearTsMsgVersionInfo();
568 24 : constexpr uint32_t sleepUsecs = 1000U; // sleep 1ms to avoid SchedWaitEvent error
569 24 : (void)usleep(sleepUsecs);
570 24 : const int32_t ret = DettachDeviceInDestroy(deviceVec);
571 24 : if (ret != AICPU_SCHEDULE_OK) {
572 2 : aicpusd_err("DettachDeviceInDestroy error %d", ret);
573 2 : return ret;
574 : }
575 22 : if ((runMode_ == aicpu::AicpuRunMode::PROCESS_PCIE_MODE) ||
576 22 : (runMode_ == aicpu::AicpuRunMode::PROCESS_SOCKET_MODE) ||
577 : waitThreadStop) {
578 21 : AicpuSchedule::ThreadPool::Instance().WaitForStop();
579 : }
580 22 : MsqOperatorManager::Finalize();
581 22 : g_aicpuProfiler.Uninit();
582 22 : aicpusd_run_info("Successfully stopped AICPU scheduler, hostPid[%d]", hostPid);
583 22 : return AICPU_SCHEDULE_OK;
584 24 : }
585 :
586 9 : int32_t AicpuScheduleInterface::GetCurrentRunMode(const bool isOnline)
587 : {
588 9 : if (!isOnline) {
589 1 : runMode_ = aicpu::AicpuRunMode::THREAD_MODE;
590 1 : aicpusd_run_info("Current aicpu mode is offline (call by api).");
591 1 : return AICPU_SCHEDULE_OK;
592 : }
593 :
594 : drvHdcCapacity capacity;
595 8 : capacity.chanType = HDC_CHAN_TYPE_SOCKET;
596 8 : capacity.maxSegment = 0U;
597 8 : const hdcError_t hdcRet = drvHdcGetCapacity(&capacity);
598 8 : if (hdcRet != DRV_ERROR_NONE) {
599 0 : aicpusd_err("Aicpu scheduler get capacity failed, ret[%d].", hdcRet);
600 0 : return AICPU_SCHEDULE_ERROR_FROM_DRV;
601 : }
602 :
603 : // online: with host, offline: without host only device
604 8 : if (capacity.chanType == HDC_CHAN_TYPE_SOCKET) {
605 7 : runMode_ = aicpu::AicpuRunMode::PROCESS_SOCKET_MODE;
606 7 : aicpusd_run_info("Set aicpu online mode false. current mode is socket_mode.");
607 7 : return AICPU_SCHEDULE_OK;
608 : }
609 :
610 1 : runMode_ = aicpu::AicpuRunMode::PROCESS_PCIE_MODE;
611 1 : aicpusd_run_info("Current aicpu mode is online (call from host).");
612 1 : return AICPU_SCHEDULE_OK;
613 : }
614 :
615 25 : int32_t AicpuScheduleInterface::DettachDeviceInDestroy(const std::vector<uint32_t> &deviceVec) const
616 : {
617 25 : if (SubModuleInterface::GetInstance().GetStartFlag()) {
618 0 : aicpusd_run_info("sub module no need to detach device, main module do it");
619 0 : return AICPU_SCHEDULE_OK;
620 : }
621 :
622 25 : DeployContext deployCtx = DeployContext::DEVICE;
623 25 : (void)GetAicpuDeployContext(deployCtx);
624 48 : for (size_t i = 0LU; i < deviceVec.size(); i++) {
625 25 : if ((FeatureCtrl::ShouldInitDrvThread()) && (deployCtx == DeployContext::DEVICE) &&
626 : (&halDrvEventThreadUninit != nullptr)) {
627 25 : const auto unInitRet = halDrvEventThreadUninit(deviceVec[i]);
628 25 : aicpusd_run_info("Uninit process drv queue msg on ccpu, ret is %d.", static_cast<int32_t>(unInitRet));
629 : (void) unInitRet;
630 : }
631 25 : const drvError_t ret = halEschedDettachDevice(deviceVec[i]);
632 25 : if ((ret != DRV_ERROR_NONE) && (ret != DRV_ERROR_NOT_EXIST)) { // maybe is repeated detach
633 2 : aicpusd_err("Failed to detach device[%u], result[%d].", deviceVec[i], ret);
634 2 : return ret;
635 : }
636 23 : aicpusd_info("Successfully detached AICPU scheduler, device[%d].", deviceVec[i]);
637 : }
638 23 : return AICPU_SCHEDULE_OK;
639 : }
640 :
641 25 : bool AicpuScheduleInterface::IsInitialized(const uint32_t deviceId)
642 : {
643 25 : const std::unique_lock<std::mutex> lockForInit(mutexForInit_);
644 25 : auto initIter = aicpusdInitFlagMap_.find(deviceId);
645 25 : if (initIter != aicpusdInitFlagMap_.end()) {
646 16 : return (initIter->second);
647 : } else {
648 9 : return false;
649 : }
650 25 : }
651 :
652 40 : void AicpuScheduleInterface::UpdateOrInsertStartFlag(const uint32_t deviceId, const bool flag)
653 : {
654 40 : auto initIter = aicpusdInitFlagMap_.find(deviceId);
655 40 : if (initIter != aicpusdInitFlagMap_.end()) {
656 34 : initIter->second = flag;
657 : } else {
658 6 : aicpusdInitFlagMap_.insert(std::pair<uint32_t, bool>(deviceId, false));
659 : }
660 40 : }
661 :
662 5 : void AicpuScheduleInterface::SetAicpuCustSdProcId(const int32_t aicpuCustSdPid)
663 : {
664 5 : if (aicpuCustSdPid != -1) {
665 5 : aicpuCustSdPid_ = aicpuCustSdPid;
666 10 : aicpusd_info("set aicpucustsd pid:%d", aicpuCustSdPid_.load());
667 : }
668 5 : }
669 :
670 2 : int32_t AicpuScheduleInterface::GetAicpuCustSdProcId() const
671 : {
672 4 : return aicpuCustSdPid_.load();
673 : }
674 :
675 9 : int32_t AicpuScheduleInterface::ProcessException(const DataFlowExceptionNotify *const exceptionInfo) const
676 : {
677 9 : aicpusd_info("Begin to process data exception event.");
678 9 : if (exceptionInfo == nullptr) {
679 1 : aicpusd_err("Invalid exception info.");
680 1 : return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
681 : }
682 :
683 8 : const auto modelNum = exceptionInfo->modelIdNum;
684 8 : const auto modelIdsAddr = PtrToPtr<void, uint32_t>(ValueToPtr(exceptionInfo->modelIdsAddr));
685 8 : if ((modelNum > 0U) && (modelIdsAddr == nullptr)) {
686 1 : aicpusd_err("Invalid modelIds.");
687 1 : return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
688 : }
689 :
690 18 : for (uint32_t i = 0; i < modelNum; ++i) {
691 13 : const auto modelId = modelIdsAddr[static_cast<size_t>(i)];
692 13 : const auto model = AicpuModelManager::GetInstance().GetModel(modelId);
693 13 : if (model == nullptr) {
694 1 : aicpusd_err("Model[%u] is not found.", modelId);
695 1 : return AICPU_SCHEDULE_ERROR_MODEL_NOT_FOUND;
696 : }
697 12 : const auto processRet = model->ProcessDataException(exceptionInfo->transId, exceptionInfo->type);
698 12 : if (processRet != AICPU_SCHEDULE_OK) {
699 1 : return processRet;
700 : }
701 11 : aicpusd_run_info("Successfully processed kernel data exception for transid[%lu] of model[%u].",
702 : exceptionInfo->transId, modelId);
703 : }
704 5 : aicpusd_info("Successfully processed kernel data exception event.");
705 5 : return AICPU_SCHEDULE_OK;
706 : }
707 :
708 26 : void AicpuScheduleInterface::SetBatchLoadMode(const uint32_t aicpuProcNum)
709 : {
710 26 : if (aicpuProcNum >= MAX_AICPU_PROC_NUM) {
711 1 : isNeedBatchLoadSo_ = false;
712 1 : aicpusd_run_info("Not need batch load so, aicpuProcNum[%u], max num[%u]",
713 : aicpuProcNum, MAX_AICPU_PROC_NUM);
714 : }
715 26 : }
716 :
717 11 : bool AicpuScheduleInterface::NeedLoadKernelSo() const
718 : {
719 11 : return isNeedBatchLoadSo_;
720 : }
721 : }
|