LCOV - code coverage report
Current view: top level - ut/foreach/foreach_addcdiv_scalar/op_host/op_api - aclnn_foreach_addcdiv_scalar_v2.cpp Coverage Total Hit
Test: CHG Lines: 50.0 % 16 8
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_addcdiv_scalar_v2.cpp
      13              :  * \brief
      14              :  */
      15              : 
      16              : #include "aclnn_foreach_addcdiv_scalar_v2.h"
      17              : #include "foreach_addcdiv_scalar_v2.h"
      18              : #include "aclnn_kernels/contiguous.h"
      19              : #include "op_api/op_api_def_nn.h"
      20              : #include "aclnn_kernels/common/op_error_check.h"
      21              : #include "opdev/op_dfx.h"
      22              : #include "opdev/make_op_executor.h"
      23              : #include "op_api/aclnn_util.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> FOREACH_ADDCDIV_SCALAR_V2_ASCEND910BC_TENSOR_DTYPE_DTYPE_SUPPORT_LIST = {
      33              :     DataType::DT_FLOAT, DataType::DT_FLOAT16, DataType::DT_BF16};
      34              : 
      35              : static const std::initializer_list<DataType> FOREACH_ADDCDIV_SCALAR_V2_FLOAT_SUPPORT_LIST = {DataType::DT_FLOAT,
      36              :                                                                                              DataType::DT_DOUBLE};
      37              : 
      38              : static const std::initializer_list<DataType> FOREACH_ADDCDIV_SCALAR_V2_FLOAT16_SUPPORT_LIST = {DataType::DT_FLOAT16,
      39              :                                                                                                DataType::DT_DOUBLE};
      40              : 
      41              : static const std::initializer_list<DataType> EMPTY_LIST = {};
      42              : 
      43              : static inline bool ForeachAddcdivScalarV2CheckNotNull(const aclTensorList* self, const aclTensorList* x2,
      44              :                                                       const aclTensorList* x3, const aclScalar* scalar,
      45              :                                                       const aclTensorList* out)
      46              : {
      47              :     OP_CHECK_NULL(self, return false);
      48              :     OP_CHECK_NULL(x2, return false);
      49              :     OP_CHECK_NULL(x3, return false);
      50              :     OP_CHECK_NULL(scalar, return false);
      51              :     OP_CHECK_NULL(out, return false);
      52              :     return true;
      53              : }
      54              : 
      55              : static inline bool ForeachAddcdivScalarV2CheckFormat(const aclTensorList* self, const aclTensorList* x2,
      56              :                                                      const aclTensorList* x3, const aclTensorList* out)
      57              : {
      58              :     for (uint64_t i = 0; i < self->Size(); i++) {
      59              :         // self格式不能是私有格式
      60              :         if (IsPrivateFormat((*self)[i]->GetStorageFormat()) || IsPrivateFormat((*x2)[i]->GetStorageFormat()) ||
      61              :             IsPrivateFormat((*x3)[i]->GetStorageFormat()) || IsPrivateFormat((*out)[i]->GetStorageFormat())) {
      62              :             OP_LOGE(ACLNN_ERR_PARAM_INVALID, "Format only support ND, NCHW, NHWC, HWCN, NDHWC, NCDHW.");
      63              :             return false;
      64              :         }
      65              :     }
      66              :     return true;
      67              : }
      68              : 
      69              : static const std::initializer_list<DataType>& ForeachAddcdivScalarV2GetDtypeSupportList()
      70              : {
      71              :     auto curArch = GetCurrentPlatformInfo().GetCurNpuArch();
      72              :     if (curArch == NpuArch::DAV_2201 || Ops::NN::AclnnUtil::IsRegbase(curArch)) {
      73              :         return FOREACH_ADDCDIV_SCALAR_V2_ASCEND910BC_TENSOR_DTYPE_DTYPE_SUPPORT_LIST;
      74              :     } else {
      75              :         OP_LOGE(ACLNN_ERR_RUNTIME_ERROR, "support for %s is not implemented",
      76              :                 op::ToString(GetCurrentPlatformInfo().GetSocVersion()).GetString());
      77              :         return EMPTY_LIST;
      78              :     }
      79              : }
      80              : 
      81              : static inline bool ForeachAddcdivScalarV2CheckDtypeValid(const aclTensorList* self, const aclTensorList* x2,
      82              :                                                          const aclTensorList* x3, const aclScalar* scalar,
      83              :                                                          const aclTensorList* out)
      84              : {
      85              :     const auto& dtypeSupportList = ForeachAddcdivScalarV2GetDtypeSupportList();
      86              :     if (dtypeSupportList.size() == 0) {
      87              :         OP_LOGE(ACLNN_ERR_PARAM_INVALID, "support for %s is not implemented",
      88              :                 op::ToString(GetCurrentPlatformInfo().GetSocVersion()).GetString());
      89              :         return false;
      90              :     }
      91              : 
      92              :     if (self->Size() == 0) {
      93              :         return true;
      94              :     }
      95              : 
      96              :     // checkself input dtype, and check the releation of input and out
      97              :     auto selfDtyte = (*self)[0]->GetDataType();
      98              :     OP_CHECK_DTYPE_NOT_SUPPORT((*self)[0], dtypeSupportList, return false);
      99              : 
     100              :     // check the releation of self and scalar
     101              :     if (selfDtyte == DataType::DT_BF16 || selfDtyte == DataType::DT_FLOAT) {
     102              :         OP_CHECK_DTYPE_NOT_SUPPORT(scalar, FOREACH_ADDCDIV_SCALAR_V2_FLOAT_SUPPORT_LIST, return false);
     103              :     } else if (selfDtyte == DataType::DT_FLOAT16) {
     104              :         OP_CHECK_DTYPE_NOT_SUPPORT(scalar, FOREACH_ADDCDIV_SCALAR_V2_FLOAT16_SUPPORT_LIST, return false);
     105              :     }
     106              : 
     107              :     for (uint64_t i = 0; i < self->Size(); i++) {
     108              :         OP_CHECK_DTYPE_NOT_MATCH((*self)[i], selfDtyte, return false);
     109              :     }
     110              : 
     111              :     for (uint64_t i = 0; i < x2->Size(); i++) {
     112              :         OP_CHECK_DTYPE_NOT_MATCH((*x2)[i], selfDtyte, return false);
     113              :         ;
     114              :     }
     115              : 
     116              :     for (uint64_t i = 0; i < x3->Size(); i++) {
     117              :         OP_CHECK_DTYPE_NOT_MATCH((*x3)[i], selfDtyte, return false);
     118              :     }
     119              :     for (uint64_t i = 0; i < out->Size(); i++) {
     120              :         OP_CHECK_DTYPE_NOT_MATCH((*out)[i], selfDtyte, return false);
     121              :     }
     122              :     return true;
     123              : }
     124              : 
     125              : static inline bool ForeachAddcdivScalarV2CheckShape(const aclTensorList* self, const aclTensorList* x2,
     126              :                                                     const aclTensorList* x3, const aclTensorList* out)
     127              : {
     128              :     // tensorlist size检查
     129              :     if (self->Size() != x2->Size()) {
     130              :         OP_LOGE(ACLNN_ERR_PARAM_INVALID, "Tensor lists must have the same number of tensors, got %lu and %lu",
     131              :                 self->Size(), x2->Size());
     132              :         return false;
     133              :     }
     134              : 
     135              :     // tensorlist size检查
     136              :     if (self->Size() != x3->Size()) {
     137              :         OP_LOGE(ACLNN_ERR_PARAM_INVALID, "Tensor lists must have the same number of tensors, got %lu and %lu",
     138              :                 self->Size(), x3->Size());
     139              :         return false;
     140              :     }
     141              : 
     142              :     // tensorlist中tensor shape一致性检查
     143              :     for (uint64_t i = 0; i < self->Size(); i++) {
     144              :         OP_CHECK_SHAPE_NOT_EQUAL((*self)[i], (*x2)[i], return false);
     145              :         OP_CHECK_SHAPE_NOT_EQUAL((*self)[i], (*x3)[i], return false);
     146              :     }
     147              : 
     148              :     // tensor 维度检查
     149              :     for (uint64_t i = 0; i < self->Size(); i++) {
     150              :         OP_CHECK_MAX_DIM((*self)[i], MAX_SUPPORT_DIMS_NUMS, return false);
     151              :     }
     152              : 
     153              :     // self和out的shape必须一致
     154              :     for (uint64_t i = 0; i < self->Size(); i++) {
     155              :         OP_CHECK_SHAPE_NOT_EQUAL((*self)[i], (*out)[i], return false);
     156              :     }
     157              :     return true;
     158              : }
     159              : 
     160              : static inline aclnnStatus ForeachAddcdivScalarV2CheckParams(const aclTensorList* self, const aclTensorList* x2,
     161              :                                                             const aclTensorList* x3, const aclScalar* scalar,
     162              :                                                             const aclTensorList* out)
     163              : {
     164              :     // 1. 检查参数是否为空指针
     165              :     CHECK_RET(ForeachAddcdivScalarV2CheckNotNull(self, x2, x3, scalar, out), ACLNN_ERR_PARAM_NULLPTR);
     166              : 
     167              :     // 检查 tensor list 内部每个条目非空,避免后续空指针解引用
     168           12 :     for (uint64_t i = 0; i < self->Size(); i++) {
     169            6 :         if ((*self)[i] == nullptr) {
     170            0 :             OP_LOGE(ACLNN_ERR_PARAM_INVALID, "self[%lu] is null.", i);
     171            0 :             return ACLNN_ERR_PARAM_INVALID;
     172              :         }
     173              :     }
     174           12 :     for (uint64_t i = 0; i < x2->Size(); i++) {
     175            6 :         if ((*x2)[i] == nullptr) {
     176            0 :             OP_LOGE(ACLNN_ERR_PARAM_INVALID, "x2[%lu] is null.", i);
     177            0 :             return ACLNN_ERR_PARAM_INVALID;
     178              :         }
     179              :     }
     180           12 :     for (uint64_t i = 0; i < x3->Size(); i++) {
     181            6 :         if ((*x3)[i] == nullptr) {
     182            0 :             OP_LOGE(ACLNN_ERR_PARAM_INVALID, "x3[%lu] is null.", i);
     183            0 :             return ACLNN_ERR_PARAM_INVALID;
     184              :         }
     185              :     }
     186           12 :     for (uint64_t i = 0; i < out->Size(); i++) {
     187            6 :         if ((*out)[i] == nullptr) {
     188            0 :             OP_LOGE(ACLNN_ERR_PARAM_INVALID, "out[%lu] is null.", i);
     189            0 :             return ACLNN_ERR_PARAM_INVALID;
     190              :         }
     191              :     }
     192              : 
     193              :     // 2. 检查输入的数据类型是否在API支持的数据类型范围之内,需要根据api定义校验
     194              :     CHECK_RET(ForeachAddcdivScalarV2CheckDtypeValid(self, x2, x3, scalar, out), ACLNN_ERR_PARAM_INVALID);
     195              :     // 3. 检查shape是否满足约束
     196              :     CHECK_RET(ForeachAddcdivScalarV2CheckShape(self, x2, x3, out), ACLNN_ERR_PARAM_INVALID);
     197              :     // 4. 检查Format是否满足约束
     198              :     CHECK_RET(ForeachAddcdivScalarV2CheckFormat(self, x2, x3, out), ACLNN_ERR_PARAM_INVALID);
     199              :     return ACLNN_SUCCESS;
     200              : }
     201              : 
     202              : static aclnnStatus ExecForeachAddcdivScalarV2GetWorkspaceSize(const aclTensorList* x1, const aclTensorList* x2,
     203              :                                                               const aclTensorList* x3, const aclScalar* scalar,
     204              :                                                               const aclTensorList* out, uint64_t* workspaceSize,
     205              :                                                               aclOpExecutor** executor)
     206              : {
     207              :     // 固定写法,创建OpExecutor
     208              :     auto uniqueExecutor = CREATE_EXECUTOR();
     209              :     CHECK_RET(uniqueExecutor.get() != nullptr, ACLNN_ERR_INNER_CREATE_EXECUTOR);
     210              : 
     211              :     // 固定写法,参数检查
     212              :     auto ret = ForeachAddcdivScalarV2CheckParams(x1, x2, x3, scalar, out);
     213              :     CHECK_RET(ret == ACLNN_SUCCESS, ret);
     214              : 
     215              :     // 空Tensorlist处理
     216              :     if (x1->Size() == 0 || x2->Size() == 0 || x3->Size() == 0) {
     217              :         *workspaceSize = 0;
     218              :         uniqueExecutor.ReleaseTo(executor);
     219              :         return ACLNN_SUCCESS;
     220              :     }
     221              : 
     222              :     // self如果非连续,需要转连续
     223              :     std::vector<const aclTensor*> tensorsVec1;
     224              :     std::vector<const aclTensor*> tensorsVec2;
     225              :     std::vector<const aclTensor*> tensorsVec3;
     226              :     for (size_t i = 0; i < x1->Size(); ++i) {
     227              :         auto secondContiguous_1 = l0op::Contiguous((*x1)[i], uniqueExecutor.get());
     228              :         CHECK_RET(secondContiguous_1 != nullptr, ACLNN_ERR_INNER_NULLPTR);
     229              :         tensorsVec1.push_back(secondContiguous_1);
     230              :     }
     231              :     auto contiguousTensorsX1 = uniqueExecutor.get()->AllocTensorList(tensorsVec1.data(), tensorsVec1.size());
     232              :     CHECK_RET(contiguousTensorsX1 != nullptr, ACLNN_ERR_INNER_NULLPTR);
     233              : 
     234              :     for (size_t i = 0; i < x2->Size(); ++i) {
     235              :         auto secondContiguous_1 = l0op::Contiguous((*x2)[i], uniqueExecutor.get());
     236              :         CHECK_RET(secondContiguous_1 != nullptr, ACLNN_ERR_INNER_NULLPTR);
     237              :         tensorsVec2.push_back(secondContiguous_1);
     238              :     }
     239              :     auto contiguousTensorsX2 = uniqueExecutor.get()->AllocTensorList(tensorsVec2.data(), tensorsVec2.size());
     240              :     CHECK_RET(contiguousTensorsX2 != nullptr, ACLNN_ERR_INNER_NULLPTR);
     241              : 
     242              :     for (size_t i = 0; i < x3->Size(); ++i) {
     243              :         auto secondContiguous_1 = l0op::Contiguous((*x3)[i], uniqueExecutor.get());
     244              :         CHECK_RET(secondContiguous_1 != nullptr, ACLNN_ERR_INNER_NULLPTR);
     245              :         tensorsVec3.push_back(secondContiguous_1);
     246              :     }
     247              :     auto contiguousTensorsX3 = uniqueExecutor.get()->AllocTensorList(tensorsVec3.data(), tensorsVec3.size());
     248              :     CHECK_RET(contiguousTensorsX3 != nullptr, ACLNN_ERR_INNER_NULLPTR);
     249              : 
     250              :     // sclar to tensor
     251              :     const aclTensor* otherTensor;
     252              :     if ((*x1)[0]->GetDataType() == DataType::DT_BF16) {
     253              :         otherTensor = uniqueExecutor.get()->ConvertToTensor(scalar, DataType::DT_FLOAT);
     254              :     } else {
     255              :         otherTensor = uniqueExecutor.get()->ConvertToTensor(scalar, (*x1)[0]->GetDataType());
     256              :     }
     257              : 
     258              :     // 调用l0算子ForeachAddcdivScalarV2进行计算
     259              :     auto result = l0op::ForeachAddcdivScalarV2(contiguousTensorsX1, contiguousTensorsX2, contiguousTensorsX3,
     260              :                                                otherTensor, out, uniqueExecutor.get());
     261              :     CHECK_RET(result != nullptr, ACLNN_ERR_INNER_NULLPTR);
     262              : 
     263              :     // 固定写法,获取计算过程中需要使用的workspace大小
     264              :     *workspaceSize = uniqueExecutor->GetWorkspaceSize();
     265              :     uniqueExecutor.ReleaseTo(executor);
     266              :     return ACLNN_SUCCESS;
     267              : }
     268              : 
     269              : aclnnStatus aclnnForeachAddcdivScalarV2GetWorkspaceSize(const aclTensorList* x1, const aclTensorList* x2,
     270              :                                                         const aclTensorList* x3, const aclScalar* scalar,
     271              :                                                         aclTensorList* out, uint64_t* workspaceSize,
     272              :                                                         aclOpExecutor** executor)
     273              : {
     274              :     L2_DFX_PHASE_1(aclnnForeachAddcdivScalarV2, DFX_IN(x1, x2, x3, scalar), DFX_OUT(out));
     275              :     return ExecForeachAddcdivScalarV2GetWorkspaceSize(x1, x2, x3, scalar, out, workspaceSize, executor);
     276              : }
     277              : 
     278              : aclnnStatus aclnnForeachAddcdivScalarV2(void* workspace, uint64_t workspaceSize, aclOpExecutor* executor,
     279              :                                         const aclrtStream stream)
     280              : {
     281              :     L2_DFX_PHASE_2(aclnnForeachAddcdivScalarV2);
     282              :     return CommonOpExecutorRun(workspace, workspaceSize, executor, stream);
     283              : }
     284              : 
     285              : #ifdef __cplusplus
     286              : }
     287              : #endif
        

Generated by: LCOV version 2.0-1