LCOV - code coverage report
Current view: top level - aicpu_schedule/core/operator_kernel/preprocess - operator_kernel_model_prepare_output.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 87.0 % 108 94
Test Date: 2026-07-28 10:54:05 Functions: 100.0 % 13 13

            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 "operator_kernel_model_prepare_output.h"
      12              : 
      13              : #include "aicpusd_status.h"
      14              : #include "aicpusd_monitor.h"
      15              : #include "aicpusd_profiler.h"
      16              : #include "aicpusd_resource_manager.h"
      17              : #include "aicpusd_model_execute.h"
      18              : #include "aicpusd_model_statistic.h"
      19              : #include "operator_kernel_common.h"
      20              : 
      21              : 
      22              : namespace AicpuSchedule {
      23              : namespace {
      24              : const std::string KERNEL_MODEL_PREPARE_OUTPUT = "modelPrepareOutput";
      25              : const std::string KERNEL_MODEL_PREPARE_OUTPUT_WITH_TENSOR_DESC = "modelPrepareOutputWithTensorDesc";
      26              : const std::string KERNEL_BUFFER_PREPARE_OUTPUT = "bufferPrepareOutput";
      27              : const std::string KERNEL_BUFFER_PREPARE_OUTPUT_WITH_TENSOR_DESC = "bufferPrepareOutputWithTensorDesc";
      28              : }  // namespace
      29              : 
      30            8 : int32_t OperatorKernelPrepareOutputBase::PrepareOutput(ProcessOutputInfo &outputInfo, const RunContext &taskContext,
      31              :                                                        const bool zeroCpy, RuntimeTensorDesc *const tensorDesc) const
      32              : {
      33              :     // point to Mbuf
      34            8 :     auto inMBuf = reinterpret_cast<Mbuf **>(static_cast<uintptr_t>(outputInfo.inMBuf));
      35            8 :     auto outMBuf = reinterpret_cast<Mbuf **>(static_cast<uintptr_t>(outputInfo.outMBuf));
      36            8 :     const bool inOrOutMbufIsNull = ((inMBuf == nullptr) || (outMBuf == nullptr));
      37            8 :     if (inOrOutMbufIsNull) {
      38            1 :         aicpusd_err("PrepareOutput param inMBuf or outMBuf is null, inMBuf[%llx], outMbuf[%llx].", outputInfo.inMBuf,
      39              :             outputInfo.outMBuf);
      40            1 :         return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
      41              :     }
      42            7 :     g_aicpuProfiler.SetPrepareOutStart();
      43            7 :     if (tensorDesc != nullptr) {
      44            1 :         if ((UINT32_MAX - static_cast<uint32_t>(sizeof(RuntimeTensorDesc))) < outputInfo.dataSize) {
      45            0 :             aicpusd_err("PrepareOutput param is invalid, output data size[%u] + sizeof(RuntimeTensorDesc)[%zu] "
      46              :                         "will overflow.", outputInfo.dataSize, sizeof(RuntimeTensorDesc));
      47            0 :             return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
      48              :         }
      49            1 :         *outMBuf = BufManager::GetInstance().MallocAndGuardBuf(
      50            1 :             outputInfo.dataSize + static_cast<uint32_t>(sizeof(RuntimeTensorDesc)), taskContext.modelId);
      51            2 :         AicpuSdModelStatistic::GetInstance().StatNNModelOutput(taskContext.modelId, tensorDesc,
      52            1 :                                                                GetStaticNNOutPutIndex(taskContext.modelId));
      53              :     } else {
      54            6 :         *outMBuf = BufManager::GetInstance().MallocAndGuardBuf(outputInfo.dataSize, taskContext.modelId);
      55              :     }
      56              : 
      57            7 :     if (*outMBuf == nullptr) {
      58            3 :         aicpusd_err("Failed to alloc mbuf, dataSize[%u], modelId[%u].", outputInfo.dataSize, taskContext.modelId);
      59            3 :         AicpuMonitor::GetInstance().SendKillMsgToTsd();
      60            3 :         return AICPU_SCHEDULE_ERROR_FROM_DRV;
      61              :     }
      62            4 :     if (tensorDesc != nullptr) {
      63            1 :         void *basePtr = nullptr;
      64            1 :         const auto ret = halMbufGetBuffAddr(*outMBuf, &basePtr);
      65            1 :         if ((ret != DRV_ERROR_NONE) || (basePtr == nullptr)) {
      66            0 :             aicpusd_err("Failed to call halMbufGetBuffAddr, ret[%d].", ret);
      67            0 :             return AICPU_SCHEDULE_ERROR_DRV_ERR;
      68              :         }
      69              : 
      70            1 :         tensorDesc->dataAddr = PtrToValue(basePtr) + static_cast<uint64_t>(sizeof(RuntimeTensorDesc));
      71            1 :         const errno_t eRet = memcpy_s(basePtr, sizeof(RuntimeTensorDesc), tensorDesc, sizeof(RuntimeTensorDesc));
      72            1 :         if (eRet != EOK) {
      73            0 :             return AICPU_SCHEDULE_ERROR_SAFE_FUNCTION_ERR;
      74              :         }
      75              :     }
      76            4 :     g_aicpuProfiler.SetPrepareOutEnd();
      77            4 :     if (!zeroCpy) {
      78            2 :         const auto ret = PrepareOutputNonZeroCpy(outputInfo, *outMBuf, tensorDesc);
      79            2 :         if (ret != AICPU_SCHEDULE_OK) {
      80            0 :             return ret;
      81              :         }
      82              :     }
      83              : 
      84            4 :     void *inputHeaderBuf = nullptr;
      85            4 :     uint32_t inputHeadSize = 0U;
      86            4 :     const auto drvRet = halMbufGetPrivInfo(*inMBuf, &inputHeaderBuf, &inputHeadSize);
      87            4 :     if (drvRet != DRV_ERROR_NONE) {
      88            1 :         aicpusd_err("Failed to get head info in input information, ret[%d].", drvRet);
      89            1 :         return AICPU_SCHEDULE_ERROR_FROM_DRV;
      90              :     }
      91            3 :     const auto ret = OperatorKernelCommon::CopyMbufHeadInfo(inputHeaderBuf, inputHeadSize, *outMBuf);
      92            3 :     if (ret != AICPU_SCHEDULE_OK) {
      93            0 :         return ret;
      94              :     }
      95              : 
      96            3 :     return AICPU_SCHEDULE_OK;
      97              : }
      98              : 
      99            3 : int32_t OperatorKernelPrepareOutputBase::PrepareOutputNonZeroCpy(const ProcessOutputInfo &outputInfo,
     100              :                                                                  Mbuf * const outMBuf,
     101              :                                                                  RuntimeTensorDesc *const tensorDesc) const
     102              : {
     103            3 :     void *dataPtr = nullptr;
     104            3 :     const auto ret = halMbufGetBuffAddr(outMBuf, &dataPtr);
     105            3 :     if ((ret != DRV_ERROR_NONE) || (dataPtr == nullptr)) {
     106            1 :         aicpusd_err("Failed to get data or data is nullptr, ret[%d].", ret);
     107            1 :         return AICPU_SCHEDULE_ERROR_DRV_ERR;
     108              :     }
     109              : 
     110            2 :     if (tensorDesc != nullptr) {
     111            1 :         dataPtr = ValueToPtr(PtrToValue(dataPtr) + sizeof(RuntimeTensorDesc));
     112              :     }
     113              : 
     114            2 :     const errno_t eRet = memcpy_s(dataPtr, static_cast<size_t>(outputInfo.dataSize),
     115            2 :         ValueToPtr(outputInfo.srcPtr),
     116            2 :         static_cast<size_t>(outputInfo.dataSize));
     117            2 :     if (eRet != EOK) {
     118            0 :         aicpusd_err("Failed to memcpy, ret[%d].", eRet);
     119            0 :         return AICPU_SCHEDULE_ERROR_SAFE_FUNCTION_ERR;
     120              :     }
     121            2 :     return AICPU_SCHEDULE_OK;
     122              : }
     123              : 
     124            1 : int32_t OperatorKernelPrepareOutputBase::GetStaticNNOutPutIndex(const uint32_t modelId) const
     125              : {
     126            1 :     const auto model = AicpuModelManager::GetInstance().GetModel(modelId);
     127            1 :     if (model == nullptr) {
     128            1 :         aicpusd_err("model:%u is null", modelId);
     129            1 :         return -1;
     130              :     }
     131            0 :     return (static_cast<int32_t>(model->GetCurStaticNNModelOutputIndex()));
     132              : }
     133              : 
     134            3 : void OperatorKernelPrepareOutputBase::MarkStaticNNOutPutIndex(const uint32_t modelId) const
     135              : {
     136            3 :     const auto model = AicpuModelManager::GetInstance().GetModel(modelId);
     137            3 :     if (model == nullptr) {
     138            3 :         aicpusd_err("model:%u is null", modelId);
     139            3 :         return;
     140              :     }
     141            0 :     model->IncreaseStaticNNModelOutputIndex();
     142            0 :     return;
     143              : }
     144              : 
     145            3 : int32_t OperatorKernelPrepareOutputBase::PrepareOutWithTensorDesc(const AicpuTaskInfo &kernelTaskInfo,
     146              :                                                                   const bool zeroCpy,
     147              :                                                                   const RunContext &taskContext) const
     148              : {
     149            3 :     MarkStaticNNOutPutIndex(taskContext.modelId);
     150            3 :     ProcessOutputInfo * const info = PtrToPtr<void, ProcessOutputInfo>(ValueToPtr(kernelTaskInfo.paraBase));
     151            3 :     if (info == nullptr) {
     152            1 :         aicpusd_err("AicpuTaskInfo.paramBase is null, modelId[%u], streamId[%u], taskId[%u]",
     153              :             taskContext.modelId, taskContext.streamId, kernelTaskInfo.taskID);
     154            1 :         return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
     155              :     }
     156            2 :     if ((UINT64_MAX - static_cast<uint64_t>(sizeof(ProcessOutputInfo))) < kernelTaskInfo.paraBase) {
     157            1 :         aicpusd_err("AicpuTaskInfo.paramBase[%lu] + sizeof(ProcessOutputInfo)[%zu] will overflow, modelId[%u], "
     158              :             "streamId[%u], taskId[%u]", kernelTaskInfo.paraBase, sizeof(ProcessOutputInfo), taskContext.modelId,
     159              :             taskContext.streamId, kernelTaskInfo.taskID);
     160            1 :         return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
     161              :     }
     162            1 :     RuntimeTensorDesc *const tensorDesc = PtrToPtr<void, RuntimeTensorDesc>(
     163            1 :         ValueToPtr(kernelTaskInfo.paraBase + static_cast<uint64_t>(sizeof(ProcessOutputInfo))));
     164            1 :     return PrepareOutput(*info, taskContext, zeroCpy, tensorDesc);
     165              : }
     166              : 
     167            3 : int32_t OperatorKernelModelPrepareOutput::Compute(const AicpuTaskInfo &kernelTaskInfo, const RunContext &taskContext)
     168              : {
     169            3 :     ProcessOutputInfo * const info = reinterpret_cast<ProcessOutputInfo *>(
     170            3 :         static_cast<uintptr_t>(kernelTaskInfo.paraBase));
     171            3 :     if (info == nullptr) {
     172            1 :         aicpusd_err("ModelPrepareOut kernelTaskInfo paramBase is null, modelId[%u], streamId[%u], taskId[%u]",
     173              :             taskContext.modelId, taskContext.streamId, kernelTaskInfo.taskID);
     174            1 :         return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
     175              :     }
     176            2 :     return PrepareOutput(*info, taskContext, false, nullptr);
     177              : }
     178              : 
     179            2 : int32_t OperatorKernelModelPrepareOutputWithTensorDesc::Compute(const AicpuTaskInfo &kernelTaskInfo,
     180              :                                                                  const RunContext &taskContext)
     181              : {
     182            2 :     return PrepareOutWithTensorDesc(kernelTaskInfo, false, taskContext);
     183              : }
     184              : 
     185            1 : int32_t OperatorKernelBufferPrepareOutput::Compute(const AicpuTaskInfo &kernelTaskInfo, const RunContext &taskContext)
     186              : {
     187            1 :     ProcessOutputInfo * const info = PtrToPtr<void, ProcessOutputInfo>(
     188            1 :         ValueToPtr(kernelTaskInfo.paraBase));
     189            1 :     if (info == nullptr) {
     190            0 :         aicpusd_err("ModelPrepareOut kernelTaskInfo paramBase is null, modelId[%u], streamId[%u], taskId[%u]",
     191              :             taskContext.modelId, taskContext.streamId, kernelTaskInfo.taskID);
     192            0 :         return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
     193              :     }
     194            1 :     return PrepareOutput(*info, taskContext, true, nullptr);
     195              : }
     196              : 
     197            1 : int32_t OperatorKernelBufferPrepareOutputWithTensorDesc::Compute(const AicpuTaskInfo &kernelTaskInfo,
     198              :                                                                   const RunContext &taskContext)
     199              : {
     200            1 :     return PrepareOutWithTensorDesc(kernelTaskInfo, true, taskContext);
     201              : }
     202              : 
     203            6 : REGISTER_OPERATOR_KERNEL(KERNEL_MODEL_PREPARE_OUTPUT, OperatorKernelModelPrepareOutput);
     204            6 : REGISTER_OPERATOR_KERNEL(KERNEL_MODEL_PREPARE_OUTPUT_WITH_TENSOR_DESC, OperatorKernelModelPrepareOutputWithTensorDesc);
     205            6 : REGISTER_OPERATOR_KERNEL(KERNEL_BUFFER_PREPARE_OUTPUT, OperatorKernelBufferPrepareOutput);
     206            6 : REGISTER_OPERATOR_KERNEL(KERNEL_BUFFER_PREPARE_OUTPUT_WITH_TENSOR_DESC, OperatorKernelBufferPrepareOutputWithTensorDesc);
     207              : }  // namespace AicpuSchedule
        

Generated by: LCOV version 2.0-1