LCOV - code coverage report
Current view: top level - aicpu_schedule/core/operator_kernel/postprocess - operator_kernel_post_process_dynamic_output.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 88.0 % 192 169
Test Date: 2026-08-12 11:05:02 Functions: 100.0 % 14 14

            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_post_process_dynamic_output.h"
      12              : 
      13              : #include "aicpusd_status.h"
      14              : #include "aicpusd_model_execute.h"
      15              : #include "aicpusd_resource_manager.h"
      16              : #include "operator_kernel_common.h"
      17              : 
      18              : namespace AicpuSchedule {
      19              : namespace {
      20              : const std::string KERNEL_POST_PROCESS_DYNAMIC_OUTPUT = "postprocessDynamicOutput";
      21              : const std::string KERNEL_POST_PROCESS_DYNAMIC_OUTPUT_V2 = "postprocessDynamicOutputV2";
      22              : 
      23              : enum class OutputType { STATIC_OUTPUT = 0, DYNAMIC_OUTPUT_WITH_MAXSIZE = 1, DYNAMIC_OUTPUT_WITHOUT_MAXSIZE = 2 };
      24              : } // namespace
      25              : 
      26            1 : int32_t OperatorKernelPostProcessDynamicOutput::Compute(
      27              :     const AicpuTaskInfo& kernelTaskInfo, const RunContext& taskContext)
      28              : {
      29            1 :     aicpusd_info(
      30              :         "Start ModelPostprocessDynamicOutput. modelId=%u, streamId=%u, taskId=%u.", taskContext.modelId,
      31              :         kernelTaskInfo.streamID, kernelTaskInfo.taskID);
      32            1 :     if (kernelTaskInfo.paraBase == 0UL) {
      33            0 :         aicpusd_err("kernelTaskInfo.paraBase is null");
      34            0 :         return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
      35              :     }
      36              : 
      37              :     const PostprocessDynamicOutputKernelArgs* const param =
      38            1 :         PtrToPtr<void, PostprocessDynamicOutputKernelArgs>(ValueToPtr(kernelTaskInfo.paraBase));
      39            1 :     if ((param->outputsNum > 0U) && ((param->outputDynamicFlagsAddr == 0U) || (param->outputMbufAddrsAddr == 0U))) {
      40            0 :         aicpusd_err(
      41              :             "Parameter invalid: outputsNum[%u], outputDynamicFlagsAddr[%u], outputMbufAddrsAddr[%u]", param->outputsNum,
      42              :             param->outputDynamicFlagsAddr, param->outputMbufAddrsAddr);
      43            0 :         return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
      44              :     }
      45              : 
      46            1 :     const auto copyRet = CopyTensorDesc(param, taskContext);
      47            1 :     if (copyRet != AICPU_SCHEDULE_OK) {
      48            0 :         return copyRet;
      49              :     }
      50              : 
      51            1 :     return FreeMbuf(param, taskContext);
      52              : }
      53              : 
      54            8 : int32_t OperatorKernelPostProcessDynamicOutput::CopyTensorDesc(
      55              :     const PostprocessDynamicOutputKernelArgs* const param, const RunContext& taskContext) const
      56              : {
      57            8 :     const uint32_t* const dynamicFlags = PtrToPtr<void, uint32_t>(ValueToPtr(param->outputDynamicFlagsAddr));
      58            8 :     uint64_t* const outputPptrs = PtrToPtr<void, uint64_t>(ValueToPtr(param->outputMbufAddrsAddr));
      59            8 :     RuntimeTensorDesc* dynamicSrcDesc = nullptr;
      60            8 :     RuntimeTensorDesc* staticSrcDesc = PtrToPtr<void, RuntimeTensorDesc>(ValueToPtr(param->outputStaticTensorDescAddr));
      61              : 
      62            8 :     void* customBuf = nullptr;
      63            8 :     uint32_t customBufSize = 0U;
      64           12 :     for (size_t index = 0U; index < param->outputsNum; ++index) {
      65           10 :         aicpusd_info("dynamicFlags[%zu] is %u.", index, dynamicFlags[index]);
      66           10 :         if (outputPptrs[index] == 0U) {
      67            1 :             aicpusd_err("the [%zu]th outputMbufPtr is null", index);
      68            1 :             return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
      69              :         }
      70              : 
      71            9 :         if ((dynamicFlags[index] == static_cast<uint32_t>(OutputType::STATIC_OUTPUT)) ||
      72            7 :             (dynamicFlags[index] == static_cast<uint32_t>(OutputType::DYNAMIC_OUTPUT_WITH_MAXSIZE))) {
      73            5 :             Mbuf* const outputMbuf = *(reinterpret_cast<Mbuf**>(outputPptrs[index]));
      74              :             const auto ret =
      75            5 :                 AllocatedOutput(param, outputMbuf, dynamicFlags[index], index, &dynamicSrcDesc, &staticSrcDesc);
      76            5 :             if (ret != AICPU_SCHEDULE_OK) {
      77            2 :                 return ret;
      78              :             }
      79            3 :             continue;
      80            3 :         }
      81              : 
      82            4 :         if (dynamicFlags[index] == static_cast<uint32_t>(OutputType::DYNAMIC_OUTPUT_WITHOUT_MAXSIZE)) {
      83            8 :             const auto getHeadRet = GetMbufHeadFromResp(
      84            4 :                 reinterpret_cast<Mbuf**>(param->respMsgMbufAddr), taskContext, &customBuf, &customBufSize);
      85            4 :             if (getHeadRet != AICPU_SCHEDULE_OK) {
      86            2 :                 return getHeadRet;
      87              :             }
      88            4 :             const auto ret = PostProcessForOutputToAllocate(
      89            2 :                 param, reinterpret_cast<Mbuf**>(outputPptrs[index]), index, &dynamicSrcDesc, customBuf, customBufSize,
      90              :                 taskContext);
      91            2 :             if (ret != AICPU_SCHEDULE_OK) {
      92            1 :                 return ret;
      93              :             }
      94              :         }
      95              :     }
      96            2 :     return AICPU_SCHEDULE_OK;
      97              : }
      98              : 
      99            8 : int32_t OperatorKernelPostProcessDynamicOutput::AllocatedOutput(
     100              :     const PostprocessDynamicOutputKernelArgs* const param, Mbuf* const outputMbuf, const uint32_t dynamicFlag,
     101              :     const size_t index, RuntimeTensorDesc** dynamicSrcDescPptr, RuntimeTensorDesc** staticSrcDescPptr) const
     102              : {
     103            8 :     if (outputMbuf == nullptr) {
     104            2 :         aicpusd_err("the [%zu]th outputMbuf is null, dynamicFlag is %u.", index, dynamicFlag);
     105            2 :         return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
     106              :     }
     107            6 :     void* dataPtr = nullptr;
     108            6 :     const auto dataRet = halMbufGetBuffAddr(outputMbuf, &dataPtr);
     109            6 :     if (dataRet != static_cast<int32_t>(DRV_ERROR_NONE)) {
     110            1 :         aicpusd_err("Failed to get data ptr, ret[%d].", dataRet);
     111            1 :         return AICPU_SCHEDULE_ERROR_FROM_DRV;
     112              :     }
     113            5 :     RuntimeTensorDesc* runtimeTensorDesc = nullptr;
     114            5 :     if (dynamicFlag > 0U) {
     115            2 :         if (*dynamicSrcDescPptr == nullptr) {
     116            2 :             const auto tensorRet = GetRuntimeTensor(param, dynamicSrcDescPptr);
     117            2 :             if (tensorRet != AICPU_SCHEDULE_OK) {
     118            0 :                 return tensorRet;
     119              :             }
     120              :         }
     121            2 :         runtimeTensorDesc = (*dynamicSrcDescPptr)++;
     122            2 :         const auto setLenRet = PostprocessSetDataLen(runtimeTensorDesc, outputMbuf, index);
     123            2 :         if (setLenRet != AICPU_SCHEDULE_OK) {
     124            1 :             return setLenRet;
     125              :         }
     126              :     } else {
     127            3 :         runtimeTensorDesc = (*staticSrcDescPptr)++;
     128              :     }
     129              : 
     130            4 :     const errno_t eRet = memcpy_s(dataPtr, sizeof(RuntimeTensorDesc), runtimeTensorDesc, sizeof(RuntimeTensorDesc));
     131            4 :     if (eRet != EOK) {
     132            1 :         aicpusd_err("Data copy failed, ret[%d].", eRet);
     133            1 :         return AICPU_SCHEDULE_ERROR_SAFE_FUNCTION_ERR;
     134              :     }
     135            3 :     return AICPU_SCHEDULE_OK;
     136              : }
     137              : 
     138            3 : int32_t OperatorKernelPostProcessDynamicOutput::GetRuntimeTensor(
     139              :     const PostprocessDynamicOutputKernelArgs* const param, RuntimeTensorDesc** dynamicSrcDescPtr) const
     140              : {
     141            3 :     Mbuf** const respPptrs = reinterpret_cast<Mbuf**>(param->respMsgMbufAddr);
     142            3 :     if (respPptrs == nullptr) {
     143            0 :         aicpusd_err("respMsgMbufAddr is null");
     144            0 :         return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
     145              :     }
     146            3 :     Mbuf* const respMbuf = *respPptrs;
     147            3 :     if (respMbuf == nullptr) {
     148            0 :         aicpusd_err("respMsgMbuf is null");
     149            0 :         return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
     150              :     }
     151            3 :     void* dataPtr = nullptr;
     152            3 :     const auto dataRet = halMbufGetBuffAddr(respMbuf, &dataPtr);
     153            3 :     if (dataRet != static_cast<int32_t>(DRV_ERROR_NONE)) {
     154            0 :         aicpusd_err("Failed to get data ptr, ret[%d].", dataRet);
     155            0 :         return AICPU_SCHEDULE_ERROR_FROM_DRV;
     156              :     }
     157              : 
     158            3 :     *dynamicSrcDescPtr = PtrToPtr<void, RuntimeTensorDesc>(dataPtr);
     159            3 :     return AICPU_SCHEDULE_OK;
     160              : }
     161              : 
     162            2 : int32_t OperatorKernelPostProcessDynamicOutput::PostprocessSetDataLen(
     163              :     const RuntimeTensorDesc* const runtimeTensorDesc, Mbuf* const outputMbuf, const size_t index) const
     164              : {
     165            2 :     const uint64_t mbufLen = runtimeTensorDesc->dataSize + static_cast<uint64_t>(sizeof(RuntimeTensorDesc));
     166            2 :     const auto setLenRet = halMbufSetDataLen(outputMbuf, mbufLen);
     167            2 :     if (setLenRet != static_cast<int32_t>(DRV_ERROR_NONE)) {
     168            1 :         uint64_t outputMbufLen = 0UL;
     169            1 :         const auto getSizeRet = halMbufGetBuffSize(outputMbuf, &outputMbufLen);
     170            1 :         if ((getSizeRet != static_cast<int32_t>(DRV_ERROR_NONE)) || (outputMbufLen < sizeof(RuntimeTensorDesc))) {
     171            0 :             aicpusd_err(
     172              :                 "Fail to get buff size for [%zu]th mbuf, ret=[%d], outputMbufLen[%lu]", index, getSizeRet,
     173              :                 outputMbufLen);
     174              :         }
     175            1 :         if (outputMbufLen >= sizeof(RuntimeTensorDesc)) {
     176            1 :             outputMbufLen -= sizeof(RuntimeTensorDesc);
     177              :         }
     178            1 :         aicpusd_err(
     179              :             "set [%zu]th mbuf's datalen to %lu fail, mbuf's len is %lu, dataSize is %lu, ret is %d", index, mbufLen,
     180              :             outputMbufLen, runtimeTensorDesc->dataSize, setLenRet);
     181            1 :         return AICPU_SCHEDULE_ERROR_FROM_DRV;
     182              :     }
     183            1 :     aicpusd_info("set [%zu]th mbuf's datalen to %lu success.", index, mbufLen);
     184            1 :     return AICPU_SCHEDULE_OK;
     185              : }
     186              : 
     187            4 : int32_t OperatorKernelPostProcessDynamicOutput::GetMbufHeadFromResp(
     188              :     Mbuf** const respMbufPtr, const RunContext& taskContext, void** const customBufPtr,
     189              :     uint32_t* const customBufSizePtr) const
     190              : {
     191            4 :     if (*customBufPtr == nullptr) {
     192            4 :         if ((respMbufPtr == nullptr) || (*respMbufPtr == nullptr)) {
     193            1 :             aicpusd_err("Invalid response Mbuf for model[%u].", taskContext.modelId);
     194            1 :             return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
     195              :         }
     196            3 :         Mbuf* const respMbuf = *respMbufPtr;
     197            3 :         const auto ret = halMbufGetPrivInfo(respMbuf, customBufPtr, customBufSizePtr);
     198            3 :         if ((ret != static_cast<int32_t>(DRV_ERROR_NONE)) || (*customBufPtr == nullptr)) {
     199            1 :             aicpusd_err("Failed to get customBuf from reponse Mbuf for model[%u], ret[%d].", taskContext.modelId, ret);
     200            1 :             return AICPU_SCHEDULE_ERROR_FROM_DRV;
     201              :         }
     202              :     }
     203            2 :     return AICPU_SCHEDULE_OK;
     204              : }
     205              : 
     206            7 : int32_t OperatorKernelPostProcessDynamicOutput::PostProcessForOutputToAllocate(
     207              :     const PostprocessDynamicOutputKernelArgs* const param, Mbuf** const outputMbufPtr, const size_t index,
     208              :     RuntimeTensorDesc** dynamicSrcDescPptr, void* const customBuf, const uint32_t customBufSize,
     209              :     const RunContext& taskContext) const
     210              : {
     211            7 :     if (*dynamicSrcDescPptr == nullptr) {
     212            2 :         const auto tensorRet = GetRuntimeTensor(param, dynamicSrcDescPptr);
     213            2 :         if (tensorRet != AICPU_SCHEDULE_OK) {
     214            0 :             return tensorRet;
     215              :         }
     216              :     }
     217              : 
     218            7 :     RuntimeTensorDesc* runtimeTensorDesc = (*dynamicSrcDescPptr)++;
     219            7 :     if (runtimeTensorDesc == nullptr) {
     220            1 :         aicpusd_err("the runtimeTensor of [%zu]th output is invalid.", index);
     221            1 :         return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
     222              :     }
     223              : 
     224            6 :     return MakeupDynamicOutputMbuf(outputMbufPtr, index, runtimeTensorDesc, customBuf, customBufSize, taskContext);
     225              : }
     226              : 
     227            6 : int32_t OperatorKernelPostProcessDynamicOutput::MakeupDynamicOutputMbuf(
     228              :     Mbuf** const outputMbufPtr, const size_t index, const RuntimeTensorDesc* const runtimeTensorDesc,
     229              :     void* const customBuf, const uint32_t customBufSize, const RunContext& taskContext) const
     230              : {
     231            6 :     const uint64_t allocSize = runtimeTensorDesc->dataSize + static_cast<uint64_t>(sizeof(RuntimeTensorDesc));
     232            6 :     Mbuf* mbuf = BufManager::GetInstance().MallocAndGuardBufU64(static_cast<uint64_t>(allocSize), taskContext.modelId);
     233            6 :     if (mbuf == nullptr) {
     234            1 :         aicpusd_err("model[%u] alloc mbuf fail, size: %zu.", taskContext.modelId, allocSize);
     235            1 :         return AICPU_SCHEDULE_ERROR_FROM_DRV;
     236              :     }
     237              : 
     238            0 :     const ScopeGuard mbufGuard([&mbuf, &taskContext]() {
     239            5 :         if (mbuf != nullptr) {
     240            4 :             aicpusd_info("Free mbuf in ScopeGuard");
     241            4 :             const auto modelPtr = AicpuModelManager::GetInstance().GetModel(taskContext.modelId);
     242            4 :             if (modelPtr == nullptr) {
     243            0 :                 aicpusd_err("cannot get aicpuModel by modelId:[%u]!", taskContext.modelId);
     244              :             }
     245            4 :             if (modelPtr != nullptr) {
     246            4 :                 (void)modelPtr->UnGardModelBuf(mbuf);
     247              :             }
     248            4 :             (void)halMbufFree(mbuf);
     249              :         }
     250            5 :     });
     251              : 
     252            5 :     const auto copyRet = OperatorKernelCommon::CopyMbufHeadInfo(customBuf, customBufSize, mbuf);
     253            5 :     if (copyRet != AICPU_SCHEDULE_OK) {
     254            1 :         aicpusd_err("model[%u] copy head fail for [%zu]th output.", taskContext.modelId, index);
     255            1 :         return copyRet;
     256              :     }
     257              : 
     258            4 :     void* dataPtr = nullptr;
     259            4 :     const auto dataRet = halMbufGetBuffAddr(mbuf, &dataPtr);
     260            4 :     if (dataRet != static_cast<int32_t>(DRV_ERROR_NONE)) {
     261            1 :         aicpusd_err("Failed to get data ptr, ret[%d].", dataRet);
     262            1 :         return AICPU_SCHEDULE_ERROR_FROM_DRV;
     263              :     }
     264              :     // copy (runtimeTensorDesc, sizeof(RuntimeTensorDesc)) to mbuf's data
     265            3 :     bool cpyRet = OptimizedMemCopy(dataPtr, sizeof(RuntimeTensorDesc), runtimeTensorDesc, sizeof(RuntimeTensorDesc));
     266            3 :     if (!cpyRet) {
     267            2 :         aicpusd_err("model[%u] copy tensordesc for [%zu]th output failed.", taskContext.modelId, index);
     268            2 :         return AICPU_SCHEDULE_ERROR_SAFE_FUNCTION_ERR;
     269              :     }
     270            1 :     dataPtr = ValueToPtr(PtrToValue(dataPtr) + sizeof(RuntimeTensorDesc));
     271              :     // copy (dataAddr, dataSize) to mbuf's offset of sizeof(RuntimeTensorDesc)
     272            2 :     cpyRet = OptimizedMemCopy(
     273            1 :         dataPtr, static_cast<size_t>(runtimeTensorDesc->dataSize), ValueToPtr(runtimeTensorDesc->dataAddr),
     274            1 :         static_cast<size_t>(runtimeTensorDesc->dataSize));
     275            1 :     if (!cpyRet) {
     276            0 :         aicpusd_err("model[%u] copy data for [%zu]th output failed.", taskContext.modelId, index);
     277            0 :         return AICPU_SCHEDULE_ERROR_SAFE_FUNCTION_ERR;
     278              :     }
     279              : 
     280            1 :     *outputMbufPtr = mbuf;
     281            1 :     mbuf = nullptr;
     282            1 :     return AICPU_SCHEDULE_OK;
     283            5 : }
     284              : 
     285            1 : bool OperatorKernelPostProcessDynamicOutput::IsSupportSdmaCopy() const { return (&halSdmaCopy != nullptr); }
     286              : 
     287            5 : bool OperatorKernelPostProcessDynamicOutput::OptimizedMemCopy(
     288              :     void* const dst_data, const size_t dst_size, const void* const src_data, const size_t src_size) const
     289              : {
     290            5 :     if (IsSupportSdmaCopy()) {
     291            1 :         const auto ret = halSdmaCopy(
     292              :             reinterpret_cast<DVdeviceptr>(dst_data), dst_size, reinterpret_cast<DVdeviceptr>(src_data), src_size);
     293            1 :         if (ret != DRV_ERROR_NONE) {
     294            1 :             aicpusd_err(
     295              :                 "Failed to call halSdmaCopy, driver api ret:%d, dst_size:%zu, src_size:%zu.", static_cast<int32_t>(ret),
     296              :                 dst_size, src_size);
     297              :         }
     298            1 :         return (ret == DRV_ERROR_NONE);
     299              :     }
     300            4 :     return AicpuUtil::BiggerMemCpy(dst_data, dst_size, src_data, src_size);
     301              : }
     302              : 
     303            2 : int32_t OperatorKernelPostProcessDynamicOutput::FreeMbuf(
     304              :     const PostprocessDynamicOutputKernelArgs* const param, const RunContext& taskContext) const
     305              : {
     306              :     // free (respMsgMbufAddr, inputMbufAddrsAddr(uniq)) and unguard them
     307            2 :     AicpuModel* const modelPtr = AicpuModelManager::GetInstance().GetModel(taskContext.modelId);
     308            2 :     if (modelPtr == nullptr) {
     309            0 :         aicpusd_err("cannot get aicpuModel by modelId:[%u]!", taskContext.modelId);
     310            0 :         return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
     311              :     }
     312            2 :     Mbuf** const respPptrs = reinterpret_cast<Mbuf**>(param->respMsgMbufAddr);
     313            2 :     if ((respPptrs != nullptr) && (*respPptrs != nullptr)) {
     314            2 :         (void)halMbufFree(*respPptrs);
     315            2 :         (void)modelPtr->UnGardModelBuf(*respPptrs);
     316              :     }
     317            2 :     if ((param->inputsNum > 0U) && (param->inputMbufAddrsAddr == 0U)) {
     318            0 :         aicpusd_err("Invalid inputsNum[%u], inputMbufAddrsAddr[%u]", param->inputsNum, param->inputMbufAddrsAddr);
     319            0 :         return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
     320              :     }
     321            2 :     uint64_t* const inputPptrs = PtrToPtr<void, uint64_t>(ValueToPtr(param->inputMbufAddrsAddr));
     322            2 :     std::unordered_set<Mbuf*> freedInput;
     323            4 :     for (size_t index = 0U; index < param->inputsNum; ++index) {
     324            2 :         Mbuf* const inputMbuf = *(reinterpret_cast<Mbuf**>(inputPptrs[index]));
     325            2 :         if (freedInput.count(inputMbuf) != 0U) {
     326            0 :             continue;
     327              :         }
     328            2 :         (void)halMbufFree(inputMbuf);
     329            2 :         (void)modelPtr->UnGardModelBuf(inputMbuf);
     330            2 :         freedInput.insert(inputMbuf);
     331              :     }
     332            2 :     return AICPU_SCHEDULE_OK;
     333            2 : }
     334              : 
     335            6 : REGISTER_OPERATOR_KERNEL(KERNEL_POST_PROCESS_DYNAMIC_OUTPUT, OperatorKernelPostProcessDynamicOutput);
     336            6 : REGISTER_OPERATOR_KERNEL(KERNEL_POST_PROCESS_DYNAMIC_OUTPUT_V2, OperatorKernelPostProcessDynamicOutput);
     337              : } // namespace AicpuSchedule
        

Generated by: LCOV version 2.0-1