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