LCOV - code coverage report
Current view: top level - aicpu_cust_schedule/core - aicpusd_threads_process.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 98.9 % 187 185
Test Date: 2026-08-12 11:05:02 Functions: 100.0 % 17 17

            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              : #include "aicpusd_threads_process.h"
      11              : 
      12              : #include "ascend_hal.h"
      13              : #include "profiling_adp.h"
      14              : #include "aicpusd_status.h"
      15              : #include "aicpusd_event_manager.h"
      16              : #include "aicpu_context.h"
      17              : #include "aicpusd_common.h"
      18              : #include "aicpusd_drv_manager.h"
      19              : #include "aicpusd_worker.h"
      20              : #include "aicpusd_monitor.h"
      21              : #include "aicpusd_hal_interface_ref.h"
      22              : #include "aicpu_prof.h"
      23              : #include "aicpu_cust_sd_dump_process.h"
      24              : #include "aicpusd_util.h"
      25              : 
      26              : namespace AicpuSchedule {
      27           18 : ComputeProcess::ComputeProcess()
      28           18 :     : deviceId_(0U),
      29           18 :       hostPid_(-1),
      30           18 :       aicpuNum_(0U),
      31           18 :       profilingMode_(PROFILING_CLOSE),
      32           18 :       aicpuPid_(-1),
      33           18 :       vfId_(0U),
      34           18 :       runMode_(aicpu::AicpuRunMode::THREAD_MODE)
      35           18 : {}
      36              : 
      37           25 : ComputeProcess& ComputeProcess::GetInstance()
      38              : {
      39           25 :     static ComputeProcess instance;
      40           25 :     return instance;
      41              : }
      42              : 
      43            8 : void ComputeProcess::UpdateProfilingSetting(uint32_t flag)
      44              : {
      45            8 :     ProfilingMode profilingMode = PROFILING_CLOSE;
      46            8 :     bool kernelFlag = false;
      47            8 :     AicpuUtil::GetProfilingInfo(flag, profilingMode, kernelFlag);
      48            8 :     profilingMode_ = profilingMode;
      49            8 :     if (kernelFlag) {
      50            1 :         aicpu::UpdateMode(profilingMode == PROFILING_OPEN);
      51              :     }
      52            8 :     aicpusd_info(
      53              :         "Update aicpu profiling mode success, flag[%u], profilingMode[%u], kernelFlag[%d],", flag, profilingMode,
      54              :         kernelFlag);
      55            8 : }
      56              : 
      57           12 : int32_t ComputeProcess::Start(
      58              :     const uint32_t deviceId, const pid_t hostPid, const uint32_t profilingMode, const pid_t aicpuPid,
      59              :     const uint32_t vfId, const aicpu::AicpuRunMode runMode)
      60              : {
      61           12 :     aicpusd_info(
      62              :         "AicpuCustSd start, deviceId[%u] hostpid[%d] profilingMode[%u] aicpuPid[%d] runMode[%d] vfId[%u].", deviceId,
      63              :         hostPid, profilingMode, aicpuPid, static_cast<int32_t>(runMode), vfId);
      64              : 
      65           12 :     const AicpuSchedule::AicpuDrvManager& drvMgr = AicpuSchedule::AicpuDrvManager::GetInstance();
      66           12 :     aicpuNum_ = drvMgr.GetAicpuNum();
      67              : 
      68           12 :     deviceId_ = deviceId;
      69           12 :     hostPid_ = hostPid;
      70           12 :     runMode_ = runMode;
      71           12 :     aicpuPid_ = aicpuPid;
      72           12 :     vfId_ = vfId;
      73              : 
      74           12 :     if ((aicpuNum_ > 0U) && (aicpu::InitTaskMonitorContext(aicpuNum_) != aicpu::AICPU_ERROR_NONE)) {
      75            1 :         aicpusd_err("Init task monitor context failed");
      76            1 :         return static_cast<int32_t>(ComputProcessRetCode::CP_RET_COMMON_ERROR);
      77              :     }
      78           11 :     if (runMode_ == aicpu::AicpuRunMode::PROCESS_PCIE_MODE) {
      79            4 :         if (&halMemBindSibling == nullptr) {
      80            0 :             aicpusd_err("Interface halMemBindSibling is not supported in current device");
      81            0 :             return AICPU_SCHEDULE_ERROR_DRV_ERR;
      82              :         }
      83            4 :         drvError_t drvRet = DRV_ERROR_NONE;
      84            4 :         if (AicpuSchedule::AicpuDrvManager::GetInstance().GetSafeVerifyFlag()) {
      85            3 :             drvRet = halMemBindSibling(hostPid, aicpuPid, vfId_, deviceId, SVM_MEM_BIND_SVM_GRP);
      86              :         } else {
      87              :             // new
      88            1 :             aicpusd_info("open prof so and bind sp group without alloc permission.");
      89            1 :             aicpu::LoadProfilingLib();
      90            1 :             drvRet = halMemBindSibling(
      91              :                 hostPid, aicpuPid, vfId_, deviceId, SVM_MEM_BIND_SVM_GRP | SVM_MEM_BIND_SP_GRP_NO_ALLOC);
      92              :         }
      93              : 
      94            4 :         if (drvRet != DRV_ERROR_NONE) {
      95            3 :             aicpusd_err(
      96              :                 "Failed to halMemBindSibling, hostpid[%d], aicpusd pid[%d], deviceId[%u], vfId[%u], ret[%d].", hostPid,
      97              :                 aicpuPid, deviceId, vfId, drvRet);
      98            3 :             return static_cast<int32_t>(ComputProcessRetCode::CP_RET_COMMON_ERROR);
      99              :         }
     100            1 :         aicpusd_info(
     101              :             "Bind Sibling pid success, hostpid[%d] aicpusd pid[%d] deviceId[%u] vfId[%u].", hostPid, aicpuPid, deviceId,
     102              :             vfId);
     103              :     }
     104            8 :     aicpu::InitProfilingDataInfo(deviceId_, hostPid, CHANNEL_CUS_AICPU);
     105            8 :     UpdateProfilingSetting(profilingMode);
     106            8 :     if (profilingMode != 0U) {
     107            8 :         aicpu::LoadProfilingLib();
     108            8 :         aicpu::SetProfilingFlagForKFC(profilingMode);
     109            8 :         aicpu::UpdateMode((profilingMode & 1) == PROFILING_OPEN);
     110              :     }
     111            8 :     (void)aicpu::SetAicpuRunMode(runMode_);
     112            8 :     aicpu::SetCustAicpuSdFlag(true);
     113            8 :     const uint32_t ret = RegisterScheduleTask();
     114            8 :     if (ret != AICPU_SCHEDULE_OK) {
     115            1 :         aicpusd_err("Register aicpu split and random kernel scheduler failed.");
     116            1 :         return static_cast<int32_t>(ret);
     117              :     }
     118              : 
     119            7 :     const int32_t aicpuStartRet = AicpuSchedule::ThreadPool::Instance().CreateWorker();
     120            7 :     if (aicpuStartRet != AICPU_SCHEDULE_OK) {
     121            1 :         aicpusd_err("Drv create aicpu work tasks failed, ret[%d].", aicpuStartRet);
     122            1 :         return static_cast<int32_t>(ComputProcessRetCode::CP_RET_COMMON_ERROR);
     123              :     }
     124            6 :     AicpuCustDumpProcess::GetInstance().InitDumpProcess(deviceId, AicpuDrvManager::GetInstance().GetAicpuNum());
     125            6 :     aicpusd_info(
     126              :         "Aicpu custom scheduler start succeed, deviceId[%u], hostpid[%d], profilingMode[%u], runMode[%d].", deviceId,
     127              :         hostPid, profilingMode, runMode_);
     128            6 :     return static_cast<int32_t>(ComputProcessRetCode::CP_RET_SUCCESS);
     129              : }
     130              : 
     131           24 : uint32_t ComputeProcess::RegisterScheduleTask()
     132              : {
     133            3 :     const auto randomKernelScheduler = [this](const aicpu::Closure& task) { return SubmitRandomKernelTask(task); };
     134              :     const auto splitKernelScheduler =
     135           10 :         [this](const uint32_t parallelId, const int64_t shardNum, const std::queue<aicpu::Closure>& taskQueue) {
     136           10 :             const AICPUSharderTaskInfo taskInfo = {.parallelId = parallelId, .shardNum = shardNum};
     137           20 :             return SubmitSplitKernelTask(taskInfo, taskQueue);
     138           24 :         };
     139            3 :     const auto splitKernelGetProcesser = [this]() { return GetAndDoSplitKernelTask(); };
     140              : 
     141           24 :     aicpu::SharderNonBlock::GetInstance().Register(
     142              :         aicpuNum_, randomKernelScheduler, splitKernelScheduler, splitKernelGetProcesser);
     143              : 
     144           24 :     return AICPU_SCHEDULE_OK;
     145              : }
     146              : 
     147            3 : uint32_t ComputeProcess::SubmitRandomKernelTask(const aicpu::Closure& task)
     148              : {
     149            3 :     if (!randomKernelTask_.Enqueue(task)) {
     150            1 :         aicpusd_err("Add random kernel task failed.");
     151            1 :         return AICPU_SCHEDULE_ERROR_INNER_ERROR;
     152              :     }
     153              : 
     154            2 :     AICPUSubEventInfo aicpuEventInfo = {};
     155            2 :     event_summary eventInfoSummary = {};
     156            2 :     eventInfoSummary.pid = getpid();
     157            2 :     eventInfoSummary.event_id = EVENT_RANDOM_KERNEL;
     158            2 :     eventInfoSummary.msg = PtrToPtr<AICPUSubEventInfo, char_t>(&aicpuEventInfo);
     159            2 :     eventInfoSummary.msg_len = static_cast<uint32_t>(sizeof(AICPUSubEventInfo));
     160              : 
     161            2 :     const int32_t drvRet = halEschedSubmitEvent(deviceId_, &eventInfoSummary);
     162            2 :     if (drvRet != DRV_ERROR_NONE) {
     163            1 :         aicpusd_err("Submit random kernel event failed. ret=%d", drvRet);
     164            1 :         return AICPU_SCHEDULE_ERROR_DRV_ERR;
     165              :     }
     166              : 
     167            1 :     return AICPU_SCHEDULE_OK;
     168              : }
     169              : 
     170           10 : uint32_t ComputeProcess::SubmitSplitKernelTask(
     171              :     const AICPUSharderTaskInfo& taskInfo, const std::queue<aicpu::Closure>& taskQueue)
     172              : {
     173           10 :     if (!splitKernelTask_.BatchAddTask(taskInfo, taskQueue)) {
     174            1 :         aicpusd_err("Add split kernel task to map failed, parallelId=%u", taskInfo.parallelId);
     175            1 :         return AICPU_SCHEDULE_ERROR_INNER_ERROR;
     176              :     }
     177              : 
     178            9 :     uint32_t ret = AICPU_SCHEDULE_OK;
     179            9 :     if (FeatureCtrl::ShouldSubmitTaskOneByOne()) {
     180            2 :         ret = SubmitBatchSplitKernelEventOneByOne(taskInfo);
     181              :     } else {
     182            7 :         ret = SubmitBatchSplitKernelEventDc(taskInfo);
     183              :     }
     184            9 :     if (ret != AICPU_SCHEDULE_OK) {
     185            2 :         aicpusd_err(
     186              :             "Submit batch split kernel event failed. parallelId=%u, submitNum=%ld", taskInfo.parallelId,
     187              :             taskInfo.shardNum);
     188            2 :         return ret;
     189              :     }
     190              : 
     191            7 :     aicpusd_info(
     192              :         "Submit split kernel event success. parallelId=%u, submitNum=%ld", taskInfo.parallelId, taskInfo.shardNum);
     193              : 
     194            7 :     return AICPU_SCHEDULE_OK;
     195              : }
     196              : 
     197            2 : uint32_t ComputeProcess::SubmitBatchSplitKernelEventOneByOne(const AICPUSharderTaskInfo& taskInfo) const
     198              : {
     199            2 :     const uint32_t submitNum = static_cast<uint32_t>(taskInfo.shardNum);
     200            3 :     for (uint32_t i = 0U; i < submitNum; ++i) {
     201            2 :         const uint32_t ret = SubmitOneSplitKernelEvent(taskInfo);
     202            2 :         if (ret != AICPU_SCHEDULE_OK) {
     203            1 :             aicpusd_err("Submit single split kernel event failed. parallelId=%u, i=%u", taskInfo.parallelId, i);
     204            1 :             return ret;
     205              :         }
     206              :     }
     207              : 
     208            1 :     return AICPU_SCHEDULE_OK;
     209              : }
     210              : 
     211            7 : uint32_t ComputeProcess::SubmitBatchSplitKernelEventDc(const AICPUSharderTaskInfo& taskInfo)
     212              : {
     213            7 :     AICPUSubEventInfo aicpuEventInfo = {};
     214            7 :     aicpuEventInfo.para.sharderTaskInfo = taskInfo;
     215            7 :     event_summary eventInfoSummary = {};
     216            7 :     eventInfoSummary.pid = getpid();
     217            7 :     eventInfoSummary.event_id = EVENT_SPLIT_KERNEL;
     218            7 :     eventInfoSummary.msg = PtrToPtr<AICPUSubEventInfo, char_t>(&aicpuEventInfo);
     219            7 :     eventInfoSummary.msg_len = static_cast<uint32_t>(sizeof(AICPUSubEventInfo));
     220            7 :     uint32_t submitSuccessNum = 0U;
     221            7 :     const uint32_t submitNum = static_cast<uint32_t>(taskInfo.shardNum);
     222              :     const int32_t drvRet =
     223            7 :         halEschedSubmitEventBatch(deviceId_, SHARED_EVENT_ENTRY, &eventInfoSummary, submitNum, &submitSuccessNum);
     224            7 :     if ((drvRet == DRV_ERROR_NONE) && (submitSuccessNum == submitNum)) {
     225            4 :         aicpusd_info(
     226              :             "Batch submit split kernel event success, parallelId=%u, submitNum=%u", taskInfo.parallelId, submitNum);
     227            4 :         return AICPU_SCHEDULE_OK;
     228              :     }
     229              : 
     230              :     /*
     231              :      * The queue depth of event schedule is only dozens. If too many split kernel event are submited,
     232              :      * the queue will be full. Therefore, the main thread needs to process the task sending failure.
     233              :      */
     234            3 :     aicpusd_warn(
     235              :         "Batch submit some of split kernel event success, ret=%d, parallelId=%u, submitNum=%u, "
     236              :         "submitSuccessNum=%u",
     237              :         drvRet, taskInfo.parallelId, submitNum, submitSuccessNum);
     238              : 
     239            3 :     const uint32_t remainNum = (drvRet == DRV_ERROR_NONE) ? submitNum - submitSuccessNum : submitNum;
     240            5 :     for (uint32_t i = 0U; i < remainNum; ++i) {
     241            3 :         if (!DoSplitKernelTask(taskInfo)) {
     242            1 :             aicpusd_err(
     243              :                 "Run single task failed after batch submit fail, parallelId=%u, submitNum=%u, "
     244              :                 "remainNum=%u, i=%u",
     245              :                 taskInfo.parallelId, submitNum, remainNum, i);
     246            1 :             return AICPU_SCHEDULE_ERROR_INNER_ERROR;
     247              :         }
     248              :     }
     249              : 
     250            2 :     return AICPU_SCHEDULE_OK;
     251              : }
     252              : 
     253            2 : uint32_t ComputeProcess::SubmitOneSplitKernelEvent(const AICPUSharderTaskInfo& taskInfo) const
     254              : {
     255            2 :     AICPUSubEventInfo aicpuEventInfo = {};
     256            2 :     aicpuEventInfo.para.sharderTaskInfo = taskInfo;
     257            2 :     event_summary eventInfoSummary = {};
     258            2 :     eventInfoSummary.pid = getpid();
     259            2 :     eventInfoSummary.event_id = EVENT_SPLIT_KERNEL;
     260            2 :     eventInfoSummary.msg = PtrToPtr<AICPUSubEventInfo, char_t>(&aicpuEventInfo);
     261            2 :     eventInfoSummary.msg_len = static_cast<uint32_t>(sizeof(AICPUSubEventInfo));
     262              : 
     263            2 :     const int32_t drvRet = halEschedSubmitEvent(deviceId_, &eventInfoSummary);
     264            2 :     if (drvRet != DRV_ERROR_NONE) {
     265            1 :         aicpusd_err("Submit split kernel event failed. ret=%d, parallelId=%u", drvRet, taskInfo.parallelId);
     266            1 :         return AICPU_SCHEDULE_ERROR_DRV_ERR;
     267              :     }
     268              : 
     269            1 :     return AICPU_SCHEDULE_OK;
     270              : }
     271              : 
     272            3 : bool ComputeProcess::GetAndDoSplitKernelTask()
     273              : {
     274            3 :     event_info eventInfo = {};
     275            3 :     const uint32_t threadIndex = aicpu::GetAicpuThreadIndex();
     276              :     const int32_t retVal =
     277            3 :         halEschedGetEvent(deviceId_, AicpuSchedule::DEFAULT_GROUP_ID, threadIndex, EVENT_SPLIT_KERNEL, &eventInfo);
     278            3 :     if (retVal == DRV_ERROR_NO_EVENT) {
     279            1 :         return true;
     280              :     }
     281            2 :     if (retVal != DRV_ERROR_NONE) {
     282            1 :         aicpusd_err("Cannot get event, threadIndex=%u, ret=%d", threadIndex, retVal);
     283            1 :         return false;
     284              :     }
     285              : 
     286            1 :     const AICPUSubEventInfo* const subEventInfo = PtrToPtr<const char_t, const AICPUSubEventInfo>(eventInfo.priv.msg);
     287            1 :     aicpusd_info(
     288              :         "Begin to process split kernel event. parallelId=%u, threadIdx=%u, type=get",
     289              :         subEventInfo->para.sharderTaskInfo.parallelId, threadIndex);
     290              : 
     291            1 :     return DoSplitKernelTask(subEventInfo->para.sharderTaskInfo);
     292              : }
     293              : 
     294            5 : bool ComputeProcess::DoSplitKernelTask(const AICPUSharderTaskInfo& taskInfo)
     295              : {
     296            5 :     aicpu::Closure task;
     297            5 :     if (!splitKernelTask_.PopTask(taskInfo, task)) {
     298            1 :         aicpusd_run_warn(
     299              :             "Get split kernel task from map failed, parallelId=%u, %s", taskInfo.parallelId,
     300              :             splitKernelTask_.DebugString().c_str());
     301            1 :         return true;
     302              :     }
     303              : 
     304              :     try {
     305            4 :         task();
     306            1 :     } catch (std::exception& e) {
     307            1 :         aicpusd_err("Run split kernel task failed. parallelId=%u, exception=%s", taskInfo.parallelId, e.what());
     308            1 :         return false;
     309            1 :     }
     310              : 
     311            3 :     return true;
     312            5 : }
     313              : 
     314            3 : bool ComputeProcess::DoRandomKernelTask()
     315              : {
     316            3 :     aicpu::Closure task;
     317            3 :     if (!randomKernelTask_.Dequeue(task)) {
     318            1 :         aicpusd_err("Get random kernel task from map failed, %s", randomKernelTask_.DebugString().c_str());
     319            1 :         return false;
     320              :     }
     321              : 
     322              :     try {
     323            2 :         task();
     324            1 :     } catch (std::exception& e) {
     325            1 :         aicpusd_err("Run random kernel task failed. exception=%s", e.what());
     326            1 :         return false;
     327            1 :     }
     328              : 
     329            1 :     return true;
     330            3 : }
     331              : 
     332            5 : void ComputeProcess::Stop()
     333              : {
     334            5 :     splitKernelTask_.Clear();
     335            5 :     randomKernelTask_.Clear();
     336            5 :     if (profilingMode_ == PROFILING_OPEN) {
     337            5 :         aicpu::ReleaseProfiling();
     338              :     }
     339            5 : }
     340              : } // namespace AicpuSchedule
        

Generated by: LCOV version 2.0-1