LCOV - code coverage report
Current view: top level - ut/foreach/foreach_round_off_number/op_host/op_api - aclnn_foreach_round_off_number_v2.cpp Coverage Total Hit
Test: CHG Lines: 50.0 % 8 4
Test Date: 2026-08-29 15:24:08
Legend: Lines: hit not hit

            Line data    Source code
       1              : /**
       2              :  * Copyright (c) 2025-2026 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              : /*!
      12              :  * \file aclnn_foreach_round_off_number_v2.cpp
      13              :  * \brief
      14              :  */
      15              : 
      16              : #include "aclnn_foreach_round_off_number_v2.h"
      17              : #include "foreach_round_off_number_v2.h"
      18              : #include "aclnn_kernels/contiguous.h"
      19              : #include "op_api/op_api_def_nn.h"
      20              : #include "op_api/aclnn_util.h"
      21              : #include "aclnn_kernels/common/op_error_check.h"
      22              : #include "opdev/op_dfx.h"
      23              : #include "opdev/make_op_executor.h"
      24              : #include "opdev/platform.h"
      25              : 
      26              : using namespace op;
      27              : 
      28              : #ifdef __cplusplus
      29              : extern "C" {
      30              : #endif
      31              : 
      32              : static const std::initializer_list<DataType> ASCEND910BC_TENSOR_DTYPE_DTYPE_SUPPORT_LIST = {
      33              :     DataType::DT_FLOAT, DataType::DT_FLOAT16, DataType::DT_BF16, DataType::DT_INT32, DataType::DT_INT16};
      34              : 
      35              : static const std::initializer_list<DataType> ASCEND950_TENSOR_DTYPE_DTYPE_SUPPORT_LIST = {
      36              :     DataType::DT_FLOAT, DataType::DT_FLOAT16, DataType::DT_BF16, DataType::DT_INT32};
      37              : 
      38              : static const std::initializer_list<DataType> FOREACH_ROUND_SCALAR_SUPPORT_LIST = {DataType::DT_INT8,
      39              :                                                                                   DataType::DT_INT64};
      40              : 
      41              : static const std::initializer_list<DataType> EMPTY_LIST = {};
      42              : 
      43              : static inline bool CheckNotNull(const aclTensorList* self, const aclScalar* scalar, const aclTensorList* out)
      44              : {
      45              :     OP_CHECK_NULL(self, return false);
      46              :     OP_CHECK_NULL(scalar, return false);
      47              :     OP_CHECK_NULL(out, return false);
      48              :     return true;
      49              : }
      50              : 
      51              : static const std::initializer_list<DataType>& GetDtypeSupportList()
      52              : {
      53              :     auto curArch = GetCurrentPlatformInfo().GetCurNpuArch();
      54              :     if (Ops::NN::AclnnUtil::IsRegbase(curArch)) {
      55              :         return ASCEND950_TENSOR_DTYPE_DTYPE_SUPPORT_LIST;
      56              :     } else if (curArch == NpuArch::DAV_2201) {
      57              :         return ASCEND910BC_TENSOR_DTYPE_DTYPE_SUPPORT_LIST;
      58              :     } else {
      59              :         OP_LOGE(ACLNN_ERR_RUNTIME_ERROR, "support for %s is not implemented",
      60              :                 op::ToString(GetCurrentPlatformInfo().GetSocVersion()).GetString());
      61              :         return EMPTY_LIST;
      62              :     }
      63              : }
      64              : 
      65              : static inline bool CheckFormat(const aclTensorList* self, const aclTensorList* out)
      66              : {
      67              :     for (uint64_t i = 0; i < self->Size(); i++) {
      68              :         // self格式不能是私有格式
      69              :         if (IsPrivateFormat((*self)[i]->GetStorageFormat()) || IsPrivateFormat((*out)[i]->GetStorageFormat())) {
      70              :             OP_LOGE(ACLNN_ERR_PARAM_INVALID, "Format only support ND, NCHW, NHWC, HWCN, NDHWC, NCDHW.");
      71              :             return false;
      72              :         }
      73              :     }
      74              :     return true;
      75              : }
      76              : 
      77              : static inline bool CheckDtypeValid(const aclTensorList* self, const aclScalar* scalar, const aclTensorList* out)
      78              : {
      79              :     const auto& dtypeSupportList = GetDtypeSupportList();
      80              :     if (dtypeSupportList.size() == 0) {
      81              :         OP_LOGE(ACLNN_ERR_PARAM_INVALID, "support for %s is not implemented",
      82              :                 op::ToString(GetCurrentPlatformInfo().GetSocVersion()).GetString());
      83              :         return false;
      84              :     }
      85              :     if (self->Size() == 0) {
      86              :         return true;
      87              :     }
      88              : 
      89              :     // checkself input dtype, and check the releation of input and out
      90              :     auto selfDtyte = (*self)[0]->GetDataType();
      91              :     OP_CHECK_DTYPE_NOT_SUPPORT((*self)[0], dtypeSupportList, return false);
      92              :     for (uint64_t b = 0; b < self->Size(); b++) {
      93              :         OP_CHECK_DTYPE_NOT_MATCH((*self)[b], selfDtyte, return false);
      94              :     }
      95              : 
      96              :     for (uint64_t b = 0; b < out->Size(); b++) {
      97              :         OP_CHECK_DTYPE_NOT_MATCH((*out)[b], selfDtyte, return false);
      98              :     }
      99              : 
     100              :     // check the releation of self and scalar
     101              :     OP_CHECK_DTYPE_NOT_SUPPORT(scalar, FOREACH_ROUND_SCALAR_SUPPORT_LIST, return false);
     102              :     return true;
     103              : }
     104              : 
     105              : static inline bool CheckShape(const aclTensorList* self, const aclTensorList* out)
     106              : {
     107              :     // tensor 维度检查
     108              :     for (uint64_t i = 0; i < self->Size(); i++) {
     109              :         OP_CHECK_MAX_DIM((*self)[i], MAX_SUPPORT_DIMS_NUMS, return false);
     110              :     }
     111              : 
     112              :     // self和out的shape必须一致
     113              :     for (uint64_t i = 0; i < self->Size(); i++) {
     114              :         OP_CHECK_SHAPE_NOT_EQUAL((*self)[i], (*out)[i], return false);
     115              :     }
     116              :     return true;
     117              : }
     118              : 
     119              : static inline aclnnStatus CheckParams(const aclTensorList* self, const aclScalar* scalar, const aclTensorList* out)
     120              : {
     121              :     // 1. 检查参数是否为空指针
     122              :     CHECK_RET(CheckNotNull(self, scalar, out), ACLNN_ERR_PARAM_NULLPTR);
     123              : 
     124              :     // Check every entry in tensor lists is not null, to avoid null pointer
     125              :     // dereference in CheckDtypeValid/CheckShape/CheckFormat.
     126           10 :     for (uint64_t i = 0; i < self->Size(); i++) {
     127            5 :         if ((*self)[i] == nullptr) {
     128            0 :             OP_LOGE(ACLNN_ERR_PARAM_INVALID, "self[%lu] is null.", i);
     129            0 :             return ACLNN_ERR_PARAM_INVALID;
     130              :         }
     131              :     }
     132           10 :     for (uint64_t i = 0; i < out->Size(); i++) {
     133            5 :         if ((*out)[i] == nullptr) {
     134            0 :             OP_LOGE(ACLNN_ERR_PARAM_INVALID, "out[%lu] is null.", i);
     135            0 :             return ACLNN_ERR_PARAM_INVALID;
     136              :         }
     137              :     }
     138              : 
     139              :     // 2. 检查输入的数据类型是否在API支持的数据类型范围之内,需要根据api定义校验
     140              :     CHECK_RET(CheckDtypeValid(self, scalar, out), ACLNN_ERR_PARAM_INVALID);
     141              :     // 3. 检查shape是否满足约束
     142              :     CHECK_RET(CheckShape(self, out), ACLNN_ERR_PARAM_INVALID);
     143              :     // 4. 检查Format是否满足约束
     144              :     CHECK_RET(CheckFormat(self, out), ACLNN_ERR_PARAM_INVALID);
     145              :     return ACLNN_SUCCESS;
     146              : }
     147              : 
     148              : static aclnnStatus ExecForeachRoundOffNumberV2GetWorkspaceSize(const aclTensorList* x, const aclScalar* scalar,
     149              :                                                                const aclTensorList* out, uint64_t* workspaceSize,
     150              :                                                                aclOpExecutor** executor)
     151              : {
     152              :     // 固定写法,创建OpExecutor
     153              :     auto uniqueExecutor = CREATE_EXECUTOR();
     154              :     CHECK_RET(uniqueExecutor.get() != nullptr, ACLNN_ERR_INNER_CREATE_EXECUTOR);
     155              : 
     156              :     // 固定写法,参数检查
     157              :     auto ret_1 = CheckParams(x, scalar, out);
     158              :     CHECK_RET(ret_1 == ACLNN_SUCCESS, ret_1);
     159              : 
     160              :     // 空Tensorlist处理
     161              :     if (x->Size() == 0) {
     162              :         *workspaceSize = 0;
     163              :         uniqueExecutor.ReleaseTo(executor);
     164              :         return ACLNN_SUCCESS;
     165              :     }
     166              : 
     167              :     // self如果非连续,需要转连续
     168              :     std::vector<const aclTensor*> tensorsVec;
     169              :     for (size_t j = 0; j < x->Size(); ++j) {
     170              :         auto secondContiguous = l0op::Contiguous((*x)[j], uniqueExecutor.get());
     171              :         CHECK_RET(secondContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR);
     172              :         tensorsVec.push_back(secondContiguous);
     173              :     }
     174              :     auto contiguousTensors = uniqueExecutor.get()->AllocTensorList(tensorsVec.data(), tensorsVec.size());
     175              :     CHECK_RET(contiguousTensors != nullptr, ACLNN_ERR_INNER_NULLPTR);
     176              : 
     177              :     // sclar to tensor
     178              :     const aclTensor* otherTensor = uniqueExecutor.get()->ConvertToTensor(scalar, DataType::DT_INT8);
     179              : 
     180              :     // 调用l0算子ForeachRoundOffNumberV2进行计算
     181              :     auto result = l0op::ForeachRoundOffNumberV2(contiguousTensors, otherTensor, out, uniqueExecutor.get());
     182              :     CHECK_RET(result != nullptr, ACLNN_ERR_INNER_NULLPTR);
     183              : 
     184              :     // 固定写法,获取计算过程中需要使用的workspace大小
     185              :     *workspaceSize = uniqueExecutor->GetWorkspaceSize();
     186              :     uniqueExecutor.ReleaseTo(executor);
     187              :     return ACLNN_SUCCESS;
     188              : }
     189              : 
     190              : aclnnStatus aclnnForeachRoundOffNumberV2GetWorkspaceSize(const aclTensorList* x, const aclScalar* roundMode,
     191              :                                                          aclTensorList* out, uint64_t* workspaceSize,
     192              :                                                          aclOpExecutor** executor)
     193              : {
     194              :     L2_DFX_PHASE_1(aclnnForeachRoundOffNumberV2, DFX_IN(x, roundMode), DFX_OUT(out));
     195              :     return ExecForeachRoundOffNumberV2GetWorkspaceSize(x, roundMode, out, workspaceSize, executor);
     196              : }
     197              : 
     198              : aclnnStatus aclnnForeachRoundOffNumberV2(void* workspace, uint64_t workspaceSize, aclOpExecutor* executor,
     199              :                                          const aclrtStream stream)
     200              : {
     201              :     L2_DFX_PHASE_2(aclnnForeachRoundOffNumberV2);
     202              :     return CommonOpExecutorRun(workspace, workspaceSize, executor, stream);
     203              : }
     204              : 
     205              : #ifdef __cplusplus
     206              : }
     207              : #endif
        

Generated by: LCOV version 2.0-1