LCOV - code coverage report
Current view: top level - ut/foreach/foreach_addcdiv_scalar/op_host/op_api - aclnn_foreach_addcdiv_scalar.cpp Coverage Total Hit
Test: CHG Lines: 0.0 % 16 0
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              : #include "aclnn_foreach_addcdiv_scalar.h"
      12              : #include "foreach_addcdiv_scalar_v2.h"
      13              : #include "../../foreach_utils/op_host/foreach_contiguous_helper.h"
      14              : #include "aclnn_kernels/contiguous.h"
      15              : #include "op_api/op_api_def_nn.h"
      16              : #include "op_api/aclnn_util.h"
      17              : #include "aclnn_kernels/common/op_error_check.h"
      18              : #include "opdev/make_op_executor.h"
      19              : #include "opdev/op_dfx.h"
      20              : #include "opdev/tensor_view_utils.h"
      21              : #include "opdev/platform.h"
      22              : 
      23              : using namespace op;
      24              : 
      25              : #ifdef __cplusplus
      26              : extern "C" {
      27              : #endif
      28              : 
      29              : static const std::initializer_list<DataType> EMPTY_LIST = {};
      30              : 
      31              : static const std::initializer_list<DataType> SCALAR_FLOAT_SUPPORT_LIST = {DataType::DT_FLOAT, DataType::DT_DOUBLE};
      32              : static const std::initializer_list<DataType> SCALAR_FLOAT16_SUPPORT_LIST = {DataType::DT_FLOAT16, DataType::DT_DOUBLE};
      33              : 
      34              : static const std::initializer_list<DataType> ASCEND910BC_TENSOR_DTYPE_DTYPE_SUPPORT_LIST = {
      35              :     DataType::DT_FLOAT, DataType::DT_FLOAT16, DataType::DT_BF16};
      36              : 
      37              : static const std::initializer_list<DataType>& GetDtypeSupportList()
      38              : {
      39              :     auto curArch = GetCurrentPlatformInfo().GetCurNpuArch();
      40              :     if (curArch != NpuArch::DAV_2201 && !Ops::NN::AclnnUtil::IsRegbase(curArch)) {
      41              :         return EMPTY_LIST;
      42              :     }
      43              :     return ASCEND910BC_TENSOR_DTYPE_DTYPE_SUPPORT_LIST;
      44              : }
      45              : 
      46              : static inline bool CheckNotNull(const aclTensorList* x1, const aclTensorList* x2, const aclTensorList* x3,
      47              :                                 const aclTensor* scalar, const aclTensorList* out)
      48              : {
      49              :     OP_CHECK_NULL(out, return false);
      50              :     OP_CHECK_NULL(x1, return false);
      51              :     OP_CHECK_NULL(x2, return false);
      52              :     OP_CHECK_NULL(x3, return false);
      53              :     OP_CHECK_NULL(scalar, return false);
      54              :     return true;
      55              : }
      56              : 
      57              : static inline bool CheckFormat(const aclTensorList* x1, const aclTensorList* x2, const aclTensorList* x3,
      58              :                                const aclTensorList* out)
      59              : {
      60              :     for (uint64_t i = 0; i < x1->Size(); i++) {
      61              :         if (IsPrivateFormat((*out)[i]->GetStorageFormat()) || IsPrivateFormat((*x1)[i]->GetStorageFormat()) ||
      62              :             IsPrivateFormat((*x2)[i]->GetStorageFormat()) || IsPrivateFormat((*x3)[i]->GetStorageFormat())) {
      63              :             OP_LOGE(ACLNN_ERR_PARAM_INVALID, "Format only support ND, NCHW, NHWC, HWCN, NDHWC, NCDHW.");
      64              :             return false;
      65              :         }
      66              :     }
      67              :     return true;
      68              : }
      69              : 
      70              : static inline bool CheckDtypeValid(const aclTensorList* x1, const aclTensorList* x2, const aclTensorList* x3,
      71              :                                    const aclTensor* scalar, const aclTensorList* out)
      72              : {
      73              :     if (x1->Size() == 0) {
      74              :         return true;
      75              :     }
      76              : 
      77              :     const auto& dtypeSupportList = GetDtypeSupportList();
      78              :     if (dtypeSupportList.size() == 0) {
      79              :         OP_LOGE(ACLNN_ERR_PARAM_INVALID, "support for %s is not implemented",
      80              :                 op::ToString(GetCurrentPlatformInfo().GetSocVersion()).GetString());
      81              :         return false;
      82              :     }
      83              : 
      84              :     auto selfDtype = (*x1)[0]->GetDataType();
      85              :     OP_CHECK_DTYPE_NOT_SUPPORT((*x1)[0], dtypeSupportList, return false);
      86              : 
      87              :     if (selfDtype == DataType::DT_BF16 || selfDtype == DataType::DT_FLOAT) {
      88              :         OP_CHECK_DTYPE_NOT_SUPPORT(scalar, SCALAR_FLOAT_SUPPORT_LIST, return false);
      89              :     } else if (selfDtype == DataType::DT_FLOAT16) {
      90              :         OP_CHECK_DTYPE_NOT_SUPPORT(scalar, SCALAR_FLOAT16_SUPPORT_LIST, return false);
      91              :     }
      92              : 
      93              :     for (uint64_t i = 0; i < out->Size(); i++) {
      94              :         OP_CHECK_DTYPE_NOT_MATCH((*out)[i], selfDtype, return false);
      95              :     }
      96              :     for (uint64_t i = 0; i < x3->Size(); i++) {
      97              :         OP_CHECK_DTYPE_NOT_MATCH((*x3)[i], selfDtype, return false);
      98              :     }
      99              :     for (uint64_t i = 0; i < x2->Size(); i++) {
     100              :         OP_CHECK_DTYPE_NOT_MATCH((*x2)[i], selfDtype, return false);
     101              :     }
     102              :     for (uint64_t i = 0; i < x1->Size(); i++) {
     103              :         OP_CHECK_DTYPE_NOT_MATCH((*x1)[i], selfDtype, return false);
     104              :     }
     105              :     return true;
     106              : }
     107              : 
     108              : static inline bool CheckShape(const aclTensorList* x1, const aclTensorList* x2, const aclTensorList* x3,
     109              :                               const aclTensorList* out)
     110              : {
     111              :     if (x1->Size() != x2->Size() || x1->Size() != x3->Size() || x1->Size() != out->Size()) {
     112              :         OP_LOGE(ACLNN_ERR_PARAM_INVALID, "Tensor lists must have the same number of tensors");
     113              :         return false;
     114              :     }
     115              : 
     116              :     for (uint64_t i = 0; i < x1->Size(); i++) {
     117              :         OP_CHECK_SHAPE_NOT_EQUAL((*x1)[i], (*out)[i], return false);
     118              :     }
     119              : 
     120              :     for (uint64_t i = 0; i < x1->Size(); i++) {
     121              :         OP_CHECK_MAX_DIM((*x1)[i], MAX_SUPPORT_DIMS_NUMS, return false);
     122              :     }
     123              : 
     124              :     for (uint64_t i = 0; i < x1->Size(); i++) {
     125              :         OP_CHECK_SHAPE_NOT_EQUAL((*x1)[i], (*x2)[i], return false);
     126              :         OP_CHECK_SHAPE_NOT_EQUAL((*x1)[i], (*x3)[i], return false);
     127              :     }
     128              :     return true;
     129              : }
     130              : 
     131              : static inline aclnnStatus CheckParams(const aclTensorList* x1, const aclTensorList* x2, const aclTensorList* x3,
     132              :                                       const aclTensor* scalar, const aclTensorList* out)
     133              : {
     134              :     CHECK_RET(CheckNotNull(x1, x2, x3, scalar, out), ACLNN_ERR_PARAM_NULLPTR);
     135              : 
     136              :     // Check every entry in tensor lists is not null, to avoid null pointer
     137              :     // dereference in CheckDtypeValid/CheckShape/CheckFormat.
     138            0 :     for (uint64_t i = 0; i < x1->Size(); i++) {
     139            0 :         if ((*x1)[i] == nullptr) {
     140            0 :             OP_LOGE(ACLNN_ERR_PARAM_INVALID, "x1[%lu] is null.", i);
     141            0 :             return ACLNN_ERR_PARAM_INVALID;
     142              :         }
     143              :     }
     144            0 :     for (uint64_t i = 0; i < x2->Size(); i++) {
     145            0 :         if ((*x2)[i] == nullptr) {
     146            0 :             OP_LOGE(ACLNN_ERR_PARAM_INVALID, "x2[%lu] is null.", i);
     147            0 :             return ACLNN_ERR_PARAM_INVALID;
     148              :         }
     149              :     }
     150            0 :     for (uint64_t i = 0; i < x3->Size(); i++) {
     151            0 :         if ((*x3)[i] == nullptr) {
     152            0 :             OP_LOGE(ACLNN_ERR_PARAM_INVALID, "x3[%lu] is null.", i);
     153            0 :             return ACLNN_ERR_PARAM_INVALID;
     154              :         }
     155              :     }
     156            0 :     for (uint64_t i = 0; i < out->Size(); i++) {
     157            0 :         if ((*out)[i] == nullptr) {
     158            0 :             OP_LOGE(ACLNN_ERR_PARAM_INVALID, "out[%lu] is null.", i);
     159            0 :             return ACLNN_ERR_PARAM_INVALID;
     160              :         }
     161              :     }
     162              : 
     163              :     CHECK_RET(CheckDtypeValid(x1, x2, x3, scalar, out), ACLNN_ERR_PARAM_INVALID);
     164              :     CHECK_RET(CheckShape(x1, x2, x3, out), ACLNN_ERR_PARAM_INVALID);
     165              :     CHECK_RET(CheckFormat(x1, x2, x3, out), ACLNN_ERR_PARAM_INVALID);
     166              :     return ACLNN_SUCCESS;
     167              : }
     168              : 
     169              : static aclnnStatus ExecForeachAddcdivScalarGetWorkspaceSize(const aclTensorList* x1, const aclTensorList* x2,
     170              :                                                             const aclTensorList* x3, const aclTensor* scalar,
     171              :                                                             const aclTensorList* out, uint64_t* workspaceSize,
     172              :                                                             aclOpExecutor** executor)
     173              : {
     174              :     auto uniqueExecutor = CREATE_EXECUTOR();
     175              :     CHECK_RET(uniqueExecutor.get() != nullptr, ACLNN_ERR_INNER_CREATE_EXECUTOR);
     176              : 
     177              :     auto ret = CheckParams(x1, x2, x3, scalar, out);
     178              :     CHECK_RET(ret == ACLNN_SUCCESS, ret);
     179              : 
     180              :     if (x1->Size() == 0 || x2->Size() == 0 || x3->Size() == 0) {
     181              :         *workspaceSize = 0;
     182              :         uniqueExecutor.ReleaseTo(executor);
     183              :         return ACLNN_SUCCESS;
     184              :     }
     185              : 
     186              :     // 输出如果非连续,需要转连续作为kernel输出buffer;连续/空则直接使用
     187              :     auto contiguousOut = ForeachMakeContiguousTensorList(out, uniqueExecutor.get());
     188              :     CHECK_RET(contiguousOut != nullptr, ACLNN_ERR_INNER_NULLPTR);
     189              : 
     190              :     // 输入如果非连续,需要转连续(空tensor直接用,保持索引一致)
     191              :     auto contiguousTensorsX3 = ForeachMakeContiguousTensorList(x3, uniqueExecutor.get());
     192              :     CHECK_RET(contiguousTensorsX3 != nullptr, ACLNN_ERR_INNER_NULLPTR);
     193              :     auto contiguousTensorsX2 = ForeachMakeContiguousTensorList(x2, uniqueExecutor.get());
     194              :     CHECK_RET(contiguousTensorsX2 != nullptr, ACLNN_ERR_INNER_NULLPTR);
     195              :     auto contiguousTensorsX1 = ForeachMakeContiguousTensorList(x1, uniqueExecutor.get());
     196              :     CHECK_RET(contiguousTensorsX1 != nullptr, ACLNN_ERR_INNER_NULLPTR);
     197              : 
     198              :     // 复用V2桥接,scalar(aclTensor*)直接透传,输出到连续buffer
     199              :     auto result = l0op::ForeachAddcdivScalarV2(contiguousTensorsX1, contiguousTensorsX2, contiguousTensorsX3, scalar,
     200              :                                                contiguousOut, uniqueExecutor.get());
     201              :     CHECK_RET(result != nullptr, ACLNN_ERR_INNER_NULLPTR);
     202              : 
     203              :     // 将连续计算结果拷贝到输出out上,out可能是非连续的tensor(空/连续跳过)
     204              :     CHECK_RET(ForeachViewCopyToOutputTensorList(contiguousOut, out, uniqueExecutor.get()), ACLNN_ERR_INNER_NULLPTR);
     205              : 
     206              :     *workspaceSize = uniqueExecutor->GetWorkspaceSize();
     207              :     uniqueExecutor.ReleaseTo(executor);
     208              :     return ACLNN_SUCCESS;
     209              : }
     210              : 
     211              : aclnnStatus aclnnForeachAddcdivScalarGetWorkspaceSize(const aclTensorList* x1, const aclTensorList* x2,
     212              :                                                       const aclTensorList* x3, const aclTensor* scalar,
     213              :                                                       aclTensorList* out, uint64_t* workspaceSize,
     214              :                                                       aclOpExecutor** executor)
     215              : {
     216              :     L2_DFX_PHASE_1(aclnnForeachAddcdivScalar, DFX_IN(x1, x2, x3, scalar), DFX_OUT(out));
     217              :     return ExecForeachAddcdivScalarGetWorkspaceSize(x1, x2, x3, scalar, out, workspaceSize, executor);
     218              : }
     219              : 
     220              : aclnnStatus aclnnForeachAddcdivScalar(void* workspace, uint64_t workspaceSize, aclOpExecutor* executor,
     221              :                                       const aclrtStream stream)
     222              : {
     223              :     L2_DFX_PHASE_2(aclnnForeachAddcdivScalar);
     224              :     return CommonOpExecutorRun(workspace, workspaceSize, executor, stream);
     225              : }
     226              : 
     227              : #ifdef __cplusplus
     228              : }
     229              : #endif
        

Generated by: LCOV version 2.0-1