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

Generated by: LCOV version 2.0-1