LCOV - code coverage report
Current view: top level - ut/compiler/graph/passes/memory_optimize - notask_pass_base.cc Coverage Total Hit
Test: CHG Lines: 100.0 % 2 2
Test Date: 2026-08-28 11:31:07
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /**
       2              :  * Copyright (c) 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 "graph/passes/memory_optimize/notask_pass_base.h"
      12              : #include "graph/utils/node_utils.h"
      13              : #include "rt_external_mem.h"
      14              : #include "graph/utils/type_utils.h"
      15              : #include "common/memory/mem_type_utils.h"
      16              : #include "common/checker.h"
      17              : #include "graph/utils/graph_utils.h"
      18              : 
      19              : namespace ge {
      20              : Status NotaskPassBase::Run(ComputeGraphPtr graph) {
      21              :   GE_CHECK_NOTNULL(graph);
      22              :   if (ShouldSkipGraph(graph)) {
      23              :     return SUCCESS;
      24              :   }
      25              : 
      26              :   for (const auto &node : graph->GetDirectNode()) {
      27              :     const auto op_desc = node->GetOpDesc();
      28              :     GE_CHECK_NOTNULL(op_desc);
      29              :     if (IsTargetOp(op_desc)) {
      30              :       RunOnTargetNode(node);
      31              :     }
      32              :   }
      33              :   return SUCCESS;
      34              : }
      35              : 
      36              : bool NotaskPassBase::ShouldSkipGraph(const ComputeGraphPtr &graph) const {
      37              :   if (ge::GraphUtils::IsSingleOpScene(graph)) {
      38              :     GELOGI("Single op scene has no need to do %s optimize.", GetOpLabel().c_str());
      39              :     return true;
      40              :   }
      41              : 
      42              :   bool is_memory_discontinuous = false;
      43              :   (void)ge::AttrUtils::GetBool(graph, ge::ATTR_NAME_MEMORY_DISCONTIGUOUS_ALLOCATION, is_memory_discontinuous);
      44              :   if (is_memory_discontinuous) {
      45              :     GELOGI("memory discontinuous scene has no need to do %s optimize.", GetOpLabel().c_str());
      46              :     return true;
      47              :   }
      48              :   return false;
      49              : }
      50              : 
      51              : void NotaskPassBase::RunOnTargetNode(const ge::NodePtr &node) {
      52              :   const auto op_desc = node->GetOpDesc();
      53              :   GELOGI("%s node [%s] start notask check.", GetOpLabel().c_str(), node->GetName().c_str());
      54              :   cur_pro_node_name_ = node->GetName();
      55              : 
      56              :   if (IsUnknownShapeOp(op_desc)) {
      57              :     GELOGI("%s node [%s] is unknown shape op.", GetOpLabel().c_str(), node->GetName().c_str());
      58              :   } else if (IsOwnerGraphUnknown(node)) {
      59              :     GELOGI("%s node [%s] is belong to unknown graph.", GetOpLabel().c_str(), node->GetName().c_str());
      60              :   } else if (!InputCheck(node)) {
      61              :     GELOGI("%s node [%s] input does not meet the conditions.", GetOpLabel().c_str(), node->GetName().c_str());
      62              :   } else if (!CheckFormat(op_desc)) {
      63              :     GELOGI("%s node [%s] format does not meet the conditions.", GetOpLabel().c_str(), node->GetName().c_str());
      64              :   } else if (!CheckDim(op_desc)) {
      65              :     GELOGI("%s node [%s] dim does not meet the conditions.", GetOpLabel().c_str(), node->GetName().c_str());
      66              :   } else if (!OutputCheck(node)) {
      67              :     GELOGI("%s node [%s] output does not meet the conditions.", GetOpLabel().c_str(), node->GetName().c_str());
      68              :   } else if (!LxFusionCheck(node)) {
      69              :     GELOGI("%s node [%s] lxFusion does not meet the conditions.", GetOpLabel().c_str(), node->GetName().c_str());
      70              :   } else {
      71              :     SetNotaskAttr(node);
      72              :   }
      73              : }
      74              : 
      75              : constexpr int32_t NOTASK_TENSOR_ALIGN_SIZE = 32;
      76              : const int32_t kNotaskDeepth = 100;
      77              : const std::string kNotaskLxSlice = "lxslice";
      78              : 
      79              : bool NotaskPassBase::CheckDimAlignment(const ge::OpDescPtr &op_desc, const gert::Shape &align_shape, const int64_t dim,
      80              :                                        const ge::GeShape &ori_shape) const {
      81              :   GE_ASSERT_TRUE(!(ori_shape.GetDimNum() <= static_cast<size_t>(dim) ||
      82              :                    align_shape.GetDimNum() <= static_cast<size_t>(dim) || align_shape[dim] <= 0),
      83              :                  "notask [%s] dim %lld, ori shape size %zu, align shape size %zu, dim value %lld.",
      84              :                  op_desc->GetName().c_str(), dim, ori_shape.GetDimNum(), align_shape.GetDimNum(), align_shape[dim]);
      85              :   if ((ori_shape.GetDim(dim) % align_shape[dim]) != 0) {
      86              :     GELOGD("notask [%s] dim %lld, ori shape %lld, align shape %lld.", op_desc->GetName().c_str(), dim,
      87              :            ori_shape.GetDim(dim), align_shape[dim]);
      88              :     return false;
      89              :   }
      90              :   return true;
      91              : }
      92              : 
      93              : void NotaskPassBase::PrintTransferDims(const std::string name,
      94              :                                        const std::vector<std::vector<int32_t>> &transfer_dims) const {
      95              :   std::stringstream ss;
      96              :   ss << "{";
      97              :   for (size_t i = 0; i < transfer_dims.size(); i++) {
      98              :     ss << "{";
      99              :     for (size_t j = 0; j < transfer_dims[i].size(); j++) {
     100              :       ss << transfer_dims[i][j];
     101              :       if (j != transfer_dims[i].size() - 1) {
     102              :         ss << ",";
     103              :       }
     104              :     }
     105              :     ss << "}";
     106              :     if (i != transfer_dims.size() - 1) {
     107              :       ss << ",";
     108              :     }
     109              :   }
     110              :   ss << "}";
     111              :   GELOGI("[%s]: %s", name.c_str(), ss.str().c_str());
     112              : }
     113              : 
     114              : void NotaskPassBase::PrintShape(const std::string name, const gert::Shape &shape) const {
     115              :   std::stringstream ss;
     116              :   ss << "{";
     117              :   for (size_t i = 0; i < shape.GetDimNum(); i++) {
     118              :     ss << shape[i];
     119              :     if (i != shape.GetDimNum() - 1) {
     120              :       ss << ",";
     121              :     }
     122              :   }
     123              :   ss << "}";
     124              :   GELOGI("[%s]: %s", name.c_str(), ss.str().c_str());
     125              : }
     126              : 
     127              : bool NotaskPassBase::CheckSplitAxis(const std::vector<int32_t> &src_axes, const int64_t &axis_idx,
     128              :                                     const int32_t &from_axis, const gert::Shape &align_shape,
     129              :                                     const gert::Shape &src_shape) const {
     130              :   const auto out = src_axes[0];
     131              :   if (out == axis_idx) {
     132              :     return src_shape.GetDim(from_axis) <= align_shape.GetDim(from_axis);
     133              :   } else {
     134              :     return align_shape.GetDim(from_axis) == 1;
     135              :   }
     136              : }
     137              : 
     138              : bool NotaskPassBase::IsFromAxisOne(const int64_t &axis_idx, const transformer::AxisIndexMapping &axis_index_mapping,
     139              :                                    const gert::Shape &align_shape, const gert::Shape &src_shape,
     140              :                                    const int32_t &from_axis) const {
     141              :   GE_ASSERT_TRUE(axis_index_mapping.src_to_dst_transfer_dims.size() > static_cast<size_t>(from_axis));
     142              :   if (axis_index_mapping.src_to_dst_transfer_dims[from_axis].size() > 1) {
     143              :     if (!CheckSplitAxis(axis_index_mapping.src_to_dst_transfer_dims[from_axis], axis_idx, from_axis, align_shape,
     144              :                         src_shape)) {
     145              :       GELOGD("The value of from axis[%d] is %lld, align shape is %lld, [%s] not meet optimize condition.", from_axis,
     146              :              src_shape.GetDim(from_axis), align_shape.GetDim(from_axis), cur_pro_node_name_.c_str());
     147              :       return false;
     148              :     }
     149              :   } else {
     150              :     return src_shape.GetDim(from_axis) == 1;
     151              :   }
     152              : 
     153              :   return true;
     154              : }
     155              : 
     156              : bool NotaskPassBase::IsMergedAxisAllOnes(const int64_t &axis_idx, const std::vector<int64_t> &shape) const {
     157              :   return shape[axis_idx] == 1;
     158              : }
     159              : 
     160              : bool NotaskPassBase::IsFrontDimsAllOnesInMergedAxis(const gert::Shape &align_shape, const gert::Shape &src_shape,
     161              :                                                     const transformer::AxisIndexMapping &axis_index_mapping,
     162              :                                                     const int64_t &real_dim, const int64_t &dim) const {
     163              :   const auto src_axes = axis_index_mapping.dst_to_src_transfer_dims[real_dim];
     164              :   const auto merge_it = std::find(src_axes.begin(), src_axes.end(), dim);
     165              :   GE_ASSERT_TRUE(merge_it != src_axes.end());
     166              :   for (auto it = src_axes.begin(); it != merge_it; it++) {
     167              :     const auto from_axis = *it;
     168              :     if (!IsFromAxisOne(real_dim, axis_index_mapping, align_shape, src_shape, from_axis)) {
     169              :       GELOGD("The value of from axis[%d] is %lld, [%s] not meet optimize condition.", from_axis,
     170              :              src_shape.GetDim(from_axis), cur_pro_node_name_.c_str());
     171              :       return false;
     172              :     }
     173              :   }
     174              :   return true;
     175              : }
     176              : 
     177              : bool NotaskPassBase::IsFrontDimsAllOnes(const transformer::AxisIndexMapping &axis_index_mapping,
     178              :                                         const std::vector<int64_t> &shape, const int64_t &real_dim) const {
     179              :   for (auto axis = 0; axis < real_dim; axis++) {
     180              :     const auto src_axes = axis_index_mapping.dst_to_src_transfer_dims[axis];
     181              :     if (src_axes.size() > 1) {
     182              :       if (!IsMergedAxisAllOnes(axis, shape)) {
     183              :         GELOGD("The value of Merged axis[%d] is %lld, [%s] not meet optimize condition.", axis, shape[axis],
     184              :                cur_pro_node_name_.c_str());
     185              :         return false;
     186              :       }
     187              :     } else {
     188              :       if (shape[axis] != 1) {
     189              :         GELOGD("The value of axis[%d] is %lld, [%s] not meet optimize condition.", axis, shape[axis],
     190              :                cur_pro_node_name_.c_str());
     191              :         return false;
     192              :       }
     193              :     }
     194              :   }
     195              : 
     196              :   return true;
     197              : }
     198              : 
     199              : bool NotaskPassBase::CheckRealDim(const gert::Shape &align_shape, const gert::Shape &src_shape,
     200              :                                   const transformer::AxisIndexMapping &axis_index_mapping, const int64_t &dim,
     201              :                                   const ge::GeTensorDesc &input_tensor) const {
     202              :   int64_t real_dim = 0;
     203              : 
     204              :   GE_ASSERT_TRUE(axis_index_mapping.src_to_dst_transfer_dims[dim].size() > 0);
     205              :   real_dim = axis_index_mapping.src_to_dst_transfer_dims[dim][0];
     206              : 
     207              :   const auto shape = input_tensor.GetShape().GetDims();
     208              :   GE_ASSERT_TRUE((real_dim >= 0) && (static_cast<size_t>(real_dim) < shape.size()));
     209              :   const auto src_real_dims = axis_index_mapping.dst_to_src_transfer_dims[real_dim];
     210              :   if (src_real_dims.size() > 1) {
     211              :     return IsFrontDimsAllOnes(axis_index_mapping, shape, real_dim) &&
     212              :            IsFrontDimsAllOnesInMergedAxis(align_shape, src_shape, axis_index_mapping, real_dim, dim);
     213              :   } else {
     214              :     return IsFrontDimsAllOnes(axis_index_mapping, shape, real_dim);
     215              :   }
     216              : }
     217              : 
     218              : bool NotaskPassBase::GetTransferDims(const ge::OpDescPtr &op_desc, const gert::Shape &src_shape,
     219              :                                      const int64_t &reshape_type_mask, const ge::GeTensorDesc &input_tensor,
     220              :                                      transformer::AxisIndexMapping &axis_index_mapping) const {
     221              :   const auto input_format = input_tensor.GetFormat();
     222              :   const ge::Format input_orinal_format = input_tensor.GetOriginFormat();
     223              :   transformer::TransferDimsInfo transfer_dims_info;
     224              :   transfer_dims_info.src_format = input_orinal_format;
     225              :   transfer_dims_info.dst_format = input_format;
     226              :   transfer_dims_info.src_shape = src_shape;
     227              :   transfer_dims_info.reshape_type_mask = reshape_type_mask;
     228              : 
     229              :   GELOGD("Node [%s] original_format=%d, format=%d, reshape_type_mask=%lld.", op_desc->GetName().c_str(),
     230              :          input_orinal_format, input_format, reshape_type_mask);
     231              :   if (!transformer::TransferShapeUtils::TransferDims(transfer_dims_info, axis_index_mapping)) {
     232              :     GELOGD("[%s] notask transfer dims failed.", op_desc->GetName().c_str());
     233              :     return false;
     234              :   }
     235              :   PrintTransferDims("src_to_dst_transfer_dims", axis_index_mapping.src_to_dst_transfer_dims);
     236              :   PrintTransferDims("dst_to_src_transfer_dims", axis_index_mapping.dst_to_src_transfer_dims);
     237              :   GE_ASSERT_TRUE(axis_index_mapping.src_to_dst_transfer_dims.size() == src_shape.GetDimNum());
     238              :   GE_ASSERT_TRUE(axis_index_mapping.dst_to_src_transfer_dims.size() == input_tensor.GetShape().GetDimNum());
     239              : 
     240              :   return true;
     241              : }
     242              : 
     243              : bool NotaskPassBase::GetAlignedShape(const ge::OpDescPtr &op_desc, const gert::Shape &src_shape,
     244              :                                      const int64_t &reshape_type_mask, const ge::GeTensorDesc &input_tensor,
     245              :                                      gert::Shape &align_shape) const {
     246              :   const auto input_format = input_tensor.GetFormat();
     247              :   const ge::Format input_orinal_format = input_tensor.GetOriginFormat();
     248              : 
     249              :   GELOGD("[%s] original_format=%d, format=%d, data_type=%d, reshape_type_mask=%lld.", op_desc->GetName().c_str(),
     250              :          input_orinal_format, input_format, input_tensor.GetDataType(), reshape_type_mask);
     251              :   transformer::AlignShapeInfo align_shape_info;
     252              :   align_shape_info.src_format = input_orinal_format;
     253              :   align_shape_info.dst_format = input_format;
     254              :   align_shape_info.src_shape = src_shape;
     255              :   align_shape_info.data_type = input_tensor.GetDataType();
     256              :   align_shape_info.reshape_type_mask = reshape_type_mask;
     257              :   if (!transformer::TransferShapeUtils::GetAlignedShape(align_shape_info, align_shape)) {
     258              :     GELOGD("notask %s get align shape failed.", op_desc->GetName().c_str());
     259              :     return false;
     260              :   }
     261              :   PrintShape("align_shape", align_shape);
     262              :   GE_ASSERT_TRUE(align_shape.GetDimNum() == src_shape.GetDimNum());
     263              :   return true;
     264              : }
     265              : 
     266              : bool NotaskPassBase::IsUnknownShapeOp(const ge::OpDescPtr &op_desc) const {
     267              :   for (auto &tenosr_desc_ptr : op_desc->GetAllInputsDescPtr()) {
     268              :     if ((tenosr_desc_ptr != nullptr) && (tenosr_desc_ptr->GetShape().IsUnknownShape())) {
     269              :       GELOGD("notask input tensor is unknown shape.");
     270              :       return true;
     271              :     }
     272              :   }
     273              : 
     274              :   for (auto &tenosr_desc_ptr : op_desc->GetAllOutputsDescPtr()) {
     275              :     if ((tenosr_desc_ptr != nullptr) && (tenosr_desc_ptr->GetShape().IsUnknownShape())) {
     276              :       GELOGD("notask output tensor is unknown shape.");
     277              :       return true;
     278              :     }
     279              :   }
     280              :   return false;
     281              : }
     282              : 
     283              : bool NotaskPassBase::OutputCheck(const ge::NodePtr &node) const {
     284              :   for (auto &output_anchor : node->GetAllOutDataAnchors()) {
     285              :     for (size_t i = 0; i < output_anchor->GetPeerInDataAnchors().size(); i++) {
     286              :       auto peerAnchor = output_anchor->GetPeerInDataAnchors().at(i);
     287              :       GE_ASSERT_TRUE(peerAnchor != nullptr);
     288              :       auto next_node = peerAnchor->GetOwnerNode();
     289              :       const auto output_nodes = next_node->GetOutDataNodes();
     290              :       if ((next_node->GetType() == RESHAPE) && (!output_nodes.empty())) {
     291              :         next_node = output_nodes.at(0);
     292              :       }
     293              :       ge::OpDescPtr next_node_desc = next_node->GetOpDesc();
     294              :       string next_node_name = next_node_desc->GetName();
     295              :       bool no_task = false;
     296              :       bool output_reuse_input = false;
     297              :       bool no_padding_continuous_input = false;
     298              :       (void)ge::AttrUtils::GetBool(next_node_desc, ge::ATTR_NAME_NOTASK, no_task);
     299              :       (void)ge::AttrUtils::GetBool(next_node_desc, ge::ATTR_NAME_OUTPUT_REUSE_INPUT, output_reuse_input);
     300              :       (void)ge::AttrUtils::GetBool(next_node_desc, ge::ATTR_NAME_NOPADDING_CONTINUOUS_INPUT,
     301              :                                    no_padding_continuous_input);
     302              :       const bool is_virtual_op = no_task || output_reuse_input || no_padding_continuous_input;
     303              :       if (is_virtual_op) {
     304              :         GELOGD("Next node %s has _no_task attribute, %s can't optimize.", next_node_name.c_str(),
     305              :                node->GetName().c_str());
     306              :         return false;
     307              :       }
     308              :     }
     309              :   }
     310              :   return true;
     311              : }
     312              : 
     313              : bool NotaskPassBase::IsOwnerGraphUnknown(const ge::NodePtr &node) const {
     314              :   bool is_dynamic = false;
     315              :   const auto &owner_graph = node->GetOwnerComputeGraph();
     316              :   if (owner_graph != nullptr) {
     317              :     (void)AttrUtils::GetBool(owner_graph, ATTR_NAME_DYNAMIC_SHAPE_PARTITIONED, is_dynamic);
     318              :     is_dynamic = (is_dynamic || owner_graph->GetGraphUnknownFlag());
     319              :   }
     320              : 
     321              :   return is_dynamic;
     322              : }
     323              : 
     324              : bool NotaskPassBase::LxFusionCheck(const ge::NodePtr &node) const {
     325              :   const auto op_desc = node->GetOpDesc();
     326              :   return !IsLxFusionMem(op_desc) && !IsLxFusionOp(node);
     327              : }
     328              : 
     329              : bool NotaskPassBase::IsLxFusionMem(const ge::OpDescPtr &op_desc) const {
     330              :   std::vector<uint32_t> input_mem_type;
     331              :   (void)ge::AttrUtils::GetListInt(op_desc, ge::ATTR_NAME_INPUT_MEM_TYPE_LIST, input_mem_type);
     332              :   std::vector<uint32_t> output_mem_type;
     333              :   (void)ge::AttrUtils::GetListInt(op_desc, ge::ATTR_NAME_OUTPUT_MEM_TYPE_LIST, output_mem_type);
     334              :   for (auto mem_type : input_mem_type) {
     335              :     if ((mem_type == RT_MEMORY_L1) || (mem_type == RT_MEMORY_L2) || (mem_type == kRtMemoryUB)) {
     336              :       GELOGD("Node [%s] has lx addr input, not optimize.", op_desc->GetName().c_str());
     337              :       return true;
     338              :     }
     339              :   }
     340              :   for (auto mem_type : output_mem_type) {
     341              :     if ((mem_type == RT_MEMORY_L1) || (mem_type == RT_MEMORY_L2) || (mem_type == kRtMemoryUB)) {
     342              :       GELOGD("Node [%s] has lx addr output, not optimize.", op_desc->GetName().c_str());
     343              :       return true;
     344              :     }
     345              :   }
     346              :   return false;
     347              : }
     348              : 
     349              : bool NotaskPassBase::IsLxFusionOp(const ge::NodePtr &node) const {
     350              :   std::string op_name = node->GetName();
     351              :   size_t pos = op_name.find(kNotaskLxSlice);
     352              :   if (pos != std::string::npos) {
     353              :     GELOGD("Node [%s] is lxfusion op, cannot optimize.", node->GetName().c_str());
     354              :     return true;
     355              :   }
     356              :   return false;
     357              : }
     358              : 
     359              : void NotaskPassBase::SetNotaskAttr(const ge::NodePtr &node) const {
     360              :   const auto op_desc = node->GetOpDesc();
     361              :   GELOGI("success to set notask attribute for node [%s]", op_desc->GetName().c_str());
     362              :   (void)ge::AttrUtils::SetBool(op_desc, ge::ATTR_NAME_NOTASK, true);
     363              :   (void)ge::AttrUtils::SetBool(op_desc, ge::ATTR_NAME_NOPADDING_CONTINUOUS_INPUT, true);
     364              :   (void)ge::AttrUtils::SetBool(op_desc, ge::ATTR_NAME_OUTPUT_REUSE_INPUT, true);
     365              :   (void)ge::AttrUtils::SetInt(op_desc, ge::ATTR_NAME_REUSE_INPUT_ON_DIM_INDEX, 0);
     366              : 
     367              :   const auto input_size = node->GetAllInDataAnchorsSize();
     368              :   for (uint32_t index = 0; index < input_size; ++index) {
     369              :     auto input_anchor = node->GetInDataAnchor(index);
     370              :     if (input_anchor == nullptr) {
     371              :       continue;
     372              :     }
     373              :     auto peer_out_anchor = input_anchor->GetPeerOutAnchor();
     374              :     if (peer_out_anchor == nullptr) {
     375              :       continue;
     376              :     }
     377              :     auto output_idx = peer_out_anchor->GetIdx();
     378              :     auto peer_node = peer_out_anchor->GetOwnerNode();
     379              :     auto output_tensor_desc = peer_node->GetOpDesc()->MutableOutputDesc(output_idx);
     380              :     if (output_tensor_desc != nullptr) {
     381              :       ge::AttrUtils::SetBool(output_tensor_desc, lock_attr_name_, false);
     382              :     }
     383              :   }
     384              : }
     385              : 
     386              : bool NotaskPassBase::InputCheck(const ge::NodePtr &node) {
     387              :   std::set<ge::OutDataAnchorPtr> src_anchors;
     388              :   std::set<int64_t> mem_types;
     389              :   for (size_t i = 0U; i < node->GetAllInDataAnchors().size(); i++) {
     390              :     const auto in_anchor = node->GetAllInDataAnchors().at(i);
     391              :     GE_CHECK_NOTNULL(in_anchor);
     392              :     const auto pre_out_anchor = in_anchor->GetPeerOutAnchor();
     393              :     if (pre_out_anchor == nullptr) {
     394              :       continue;
     395              :     }
     396              :     auto output_idx = pre_out_anchor->GetIdx();
     397              :     auto pre_node = pre_out_anchor->GetOwnerNode();
     398              :     auto pre_op_desc = pre_node->GetOpDesc();
     399              : 
     400              :     if (IsScalarInput(node, i)) {
     401              :       GELOGD("Node [%s] has scalar input[%zu] which does not meet optimize condition.", cur_pro_node_name_.c_str(), i);
     402              :       return false;
     403              :     }
     404              : 
     405              :     if (!CheckTensorAlign(node, i)) {
     406              :       GELOGD("node [%s] check tensor align failed.", node->GetName().c_str());
     407              :       return false;
     408              :     }
     409              : 
     410              :     if (HasSameSourceAnchor(in_anchor, src_anchors)) {
     411              :       GELOGD("node [%s] has same source anchor.", node->GetName().c_str());
     412              :       return false;
     413              :     }
     414              : 
     415              :     if (!IsPreNodeTypeValid(in_anchor)) {
     416              :       return false;
     417              :     }
     418              : 
     419              :     if (IsPreNodeWithSubgraph(in_anchor)) {
     420              :       GELOGD("Pre node [%s] has subgraph, [%s] can't optimize.", pre_node->GetName().c_str(), node->GetName().c_str());
     421              :       return false;
     422              :     }
     423              : 
     424              :     if (!IsPreOutAnchorCanReuse(pre_out_anchor)) {
     425              :       GELOGD("node [%s] pre node [%s] cannot reused.", node->GetName().c_str(), pre_node->GetName().c_str());
     426              :       return false;
     427              :     }
     428              : 
     429              :     if (!IsPreOutAnchorValidMultiRef(pre_out_anchor)) {
     430              :       GELOGD("Previous node [%s] connect to netoutput, [%s] can't optimize.", pre_node->GetName().c_str(),
     431              :              cur_pro_node_name_.c_str());
     432              :       return false;
     433              :     }
     434              : 
     435              :     if (!IsPreNodeAttrValid(pre_op_desc)) {
     436              :       return false;
     437              :     }
     438              : 
     439              :     if (!IsSameInputMemType(pre_op_desc, output_idx, mem_types)) {
     440              :       GELOGD("Input mem type is not same, [%s] can't optimize.", cur_pro_node_name_.c_str());
     441              :       return false;
     442              :     }
     443              :   }
     444              :   return true;
     445              : }
     446              : 
     447              : bool NotaskPassBase::IsScalarInput(const ge::NodePtr &node, const size_t input_index) const {
     448              :   const auto td = node->GetOpDesc()->GetInputDesc(input_index);
     449              :   return td.GetOriginShape().GetDimNum() == 0;
     450              : }
     451              : 
     452              : bool NotaskPassBase::CheckTensorAlign(const ge::NodePtr &node, const size_t input_index) const {
     453              :   if (node->GetAllInDataAnchorsSize() == 1) {
     454              :     return true;
     455              :   }
     456              : 
     457              :   const auto td = node->GetOpDesc()->GetInputDesc(input_index);
     458              :   const auto shape_size = td.GetShape().GetShapeSize();
     459              :   if (ge::GetSizeByDataType(td.GetDataType()) < 0) {
     460              :     GELOGI("Get data type[%s] size less than zero.", ge::TypeUtils::DataTypeToSerialString(td.GetDataType()).c_str());
     461              :     return false;
     462              :   }
     463              :   const auto tensor_size = ge::GetSizeInBytes(shape_size, td.GetDataType());
     464              :   return ((tensor_size > 0) && (tensor_size % NOTASK_TENSOR_ALIGN_SIZE == 0));
     465              : }
     466              : 
     467              : bool NotaskPassBase::HasSameSourceAnchor(const ge::InDataAnchorPtr &in_anchor,
     468              :                                          std::set<ge::OutDataAnchorPtr> &src_anchors) const {
     469              :   ge::OutDataAnchorPtr src_anchor = nullptr;
     470              :   GetFirstOutAnchorNotInRefNode(in_anchor, src_anchor, 0);
     471              :   const bool has_same_src_anchor = (src_anchors.count(src_anchor) == 1U);
     472              :   src_anchors.insert(src_anchor);
     473              :   return has_same_src_anchor;
     474              : }
     475              : 
     476              : bool NotaskPassBase::IsPreNodeWithSubgraph(const ge::InDataAnchorPtr &in_anchor) const {
     477              :   ge::NodePtr node = nullptr;
     478              : 
     479              :   GetFirstNotRefNode(in_anchor, node);
     480              :   if (node == nullptr) {
     481              :     return false;
     482              :   }
     483              :   const auto op_desc = node->GetOpDesc();
     484              :   return (op_desc != nullptr) ? (!op_desc->GetSubgraphInstanceNames().empty()) : false;
     485              : }
     486              : 
     487           91 : bool NotaskPassBase::IsPreNodeTypeValid(const ge::InDataAnchorPtr &in_anchor) const {
     488              :   ge::NodePtr node = nullptr;
     489              : 
     490              :   GetFirstNotRefNode(in_anchor, node);
     491              :   if (node == nullptr) {
     492              :     return false;
     493              :   }
     494              :   const std::string op_type = node->GetType();
     495              :   static std::set<std::string> not_support_type = {DATA, REFDATA, VARIABLE, CONSTANTOP, CONSTANT};
     496              :   if (not_support_type.count(op_type) != 0U) {
     497              :     GELOGD("node [%s] pre node [%s] opType is %s.", cur_pro_node_name_.c_str(), node->GetName().c_str(),
     498              :            op_type.c_str());
     499              :     return false;
     500              :   }
     501              : 
     502              :   return true;
     503              : }
     504              : 
     505              : bool NotaskPassBase::IsPreOutAnchorCanReuse(const ge::OutDataAnchorPtr out_anchor) const {
     506              :   auto peer_node = out_anchor->GetOwnerNode();
     507              :   auto output_idx = out_anchor->GetIdx();
     508              :   auto output_tensor_desc = peer_node->GetOpDesc()->MutableOutputDesc(output_idx);
     509              :   if (output_tensor_desc == nullptr) {
     510              :     return false;
     511              :   }
     512              :   bool can_reuse = true;
     513              :   (void)ge::AttrUtils::GetBool(output_tensor_desc, lock_attr_name_, can_reuse);
     514              :   return can_reuse;
     515              : }
     516              : 
     517              : bool NotaskPassBase::IsPreOutAnchorValidMultiRef(const ge::OutDataAnchorPtr out_anchor) const {
     518              :   auto in_anchors = out_anchor->GetPeerInDataAnchors();
     519              :   if (in_anchors.size() == 1U) {
     520              :     return true;
     521              :   }
     522              : 
     523              :   for (const auto &anchor : in_anchors) {
     524              :     if (anchor->GetOwnerNode()->GetType() == NETOUTPUT) {
     525              :       return false;
     526              :     }
     527              :   }
     528              :   return true;
     529              : }
     530              : 
     531           81 : bool NotaskPassBase::IsPreNodeAttrValid(const ge::OpDescPtr &pre_op_desc) const {
     532              :   string pre_node_name = pre_op_desc->GetName();
     533              :   bool is_continous_input = false;
     534              :   bool is_continous_output = false;
     535              :   bool is_ref = false;
     536              :   bool no_task = false;
     537              :   bool output_reuse_input = false;
     538              :   bool no_padding_continuous_input = false;
     539              :   vector<int64_t> output_index;
     540              :   (void)ge::AttrUtils::GetBool(pre_op_desc, ge::ATTR_NAME_CONTINUOUS_INPUT, is_continous_input);
     541              :   (void)ge::AttrUtils::GetBool(pre_op_desc, ge::ATTR_NAME_CONTINUOUS_OUTPUT, is_continous_output);
     542              :   (void)ge::AttrUtils::GetBool(pre_op_desc, ge::ATTR_NAME_REFERENCE, is_ref);
     543              :   (void)ge::AttrUtils::GetListInt(pre_op_desc, ge::ATOMIC_ATTR_OUTPUT_INDEX, output_index);
     544              :   (void)ge::AttrUtils::GetBool(pre_op_desc, ge::ATTR_NAME_NOTASK, no_task);
     545              :   (void)ge::AttrUtils::GetBool(pre_op_desc, ge::ATTR_NAME_OUTPUT_REUSE_INPUT, output_reuse_input);
     546              :   (void)ge::AttrUtils::GetBool(pre_op_desc, ge::ATTR_NAME_NOPADDING_CONTINUOUS_INPUT, no_padding_continuous_input);
     547              : 
     548              :   if (is_continous_input || is_continous_output || is_ref) {
     549              :     GELOGD(
     550              :         "Previous node %s attribute: continuous_input %s, continuous_output %s,"
     551              :         " reference %s, node %s can't optimize.",
     552              :         pre_node_name.c_str(), is_continous_input ? "true" : "false", is_continous_output ? "true" : "false",
     553              :         is_ref ? "true" : "false", cur_pro_node_name_.c_str());
     554              :     return false;
     555              :   }
     556              : 
     557              :   bool is_virtual_op = no_task || output_reuse_input || no_padding_continuous_input;
     558              :   if (is_virtual_op) {
     559              :     GELOGD("Previous node %s has _no_task attribute, %s can't optimize.", pre_node_name.c_str(),
     560              :            cur_pro_node_name_.c_str());
     561              :     return false;
     562              :   }
     563              :   if (!output_index.empty()) {
     564              :     GELOGD("Previous node %s has atomic output, %s cannot optimize.", pre_node_name.c_str(),
     565              :            cur_pro_node_name_.c_str());
     566              :     return false;
     567              :   }
     568              : 
     569              :   return true;
     570              : }
     571              : 
     572              : bool NotaskPassBase::IsSameInputMemType(const ge::OpDescPtr &pre_op_desc, const size_t output_idx,
     573              :                                         std::set<int64_t> &mem_types) const {
     574              :   std::vector<int64_t> output_mem_type;
     575              :   int64_t mem_type = RT_MEMORY_HBM;
     576              :   (void)ge::AttrUtils::GetListInt(pre_op_desc, ge::ATTR_NAME_OUTPUT_MEM_TYPE_LIST, output_mem_type);
     577              :   if (output_idx < output_mem_type.size()) {
     578              :     if (MemTypeUtils::IsMemoryTypeSpecial(output_mem_type[output_idx])) {
     579              :       mem_type = output_mem_type[output_idx];
     580              :     }
     581              :   }
     582              :   mem_types.insert(mem_type);
     583              : 
     584              :   return (mem_types.size() == 1);
     585              : }
     586              : 
     587              : void NotaskPassBase::GetFirstOutAnchorNotInRefNode(const ge::InDataAnchorPtr &input_anchor,
     588              :                                                    ge::OutDataAnchorPtr &src_anchor, int32_t current_deep) const {
     589              :   if (current_deep >= kNotaskDeepth) {
     590              :     return;
     591              :   }
     592              :   auto peer_out_anchor = input_anchor->GetPeerOutAnchor();
     593              :   if (peer_out_anchor == nullptr) {
     594              :     return;
     595              :   }
     596              :   auto peer_node = peer_out_anchor->GetOwnerNode();
     597              :   if (peer_node == nullptr) {
     598              :     return;
     599              :   }
     600              :   int32_t reuse_in_index = -1;
     601              :   const bool reuse_input_flag = GraphUtils::IsRefFromInput(peer_out_anchor, reuse_in_index);
     602              :   if (reuse_input_flag) {
     603              :     auto in_anchor = peer_node->GetInDataAnchor(reuse_in_index);
     604              :     if (in_anchor == nullptr) {
     605              :       return;
     606              :     }
     607              :     GetFirstOutAnchorNotInRefNode(in_anchor, src_anchor, current_deep + 1);
     608              :   } else {
     609              :     src_anchor = peer_out_anchor;
     610              :   }
     611              :   return;
     612              : }
     613              : 
     614              : void NotaskPassBase::GetFirstNotRefNode(const ge::InDataAnchorPtr &input_anchor, ge::NodePtr &node) const {
     615              :   ge::OutDataAnchorPtr src_anchor = nullptr;
     616              :   GetFirstOutAnchorNotInRefNode(input_anchor, src_anchor, 0);
     617              :   node = (src_anchor != nullptr) ? src_anchor->GetOwnerNode() : nullptr;
     618              :   return;
     619              : }
     620              : 
     621              : bool NotaskPassBase::CheckDimForInput(const ge::OpDescPtr &op_desc, int64_t check_dim, size_t input_idx) const {
     622              :   ge::GeTensorDesc input_tensor = op_desc->GetInputDesc(input_idx);
     623              :   ge::GeShape input_orinal_shape = input_tensor.GetOriginShape();
     624              :   gert::Shape src_shape;
     625              :   src_shape.SetDimNum(input_orinal_shape.GetDimNum());
     626              :   for (size_t j = 0; j < src_shape.GetDimNum(); j++) {
     627              :     src_shape[j] = input_orinal_shape.GetDim(j);
     628              :   }
     629              :   PrintShape("src_shape", src_shape);
     630              :   int64_t reshape_type_mask = 0;
     631              :   (void)ge::AttrUtils::GetInt(input_tensor, ge::ATTR_NAME_RESHAPE_TYPE_MASK, reshape_type_mask);
     632              : 
     633              :   gert::Shape align_shape;
     634              :   if (!GetAlignedShape(op_desc, src_shape, reshape_type_mask, input_tensor, align_shape)) {
     635              :     return false;
     636              :   }
     637              : 
     638              :   transformer::AxisIndexMapping axis_index_mapping;
     639              :   if (!GetTransferDims(op_desc, src_shape, reshape_type_mask, input_tensor, axis_index_mapping)) {
     640              :     return false;
     641              :   }
     642              : 
     643              :   if (!CheckRealDim(align_shape, src_shape, axis_index_mapping, check_dim, input_tensor)) {
     644              :     GELOGD("[%s] notask check real dim failed, dim = %lld.", op_desc->GetName().c_str(), check_dim);
     645              :     return false;
     646              :   }
     647              : 
     648              :   if (!CheckDimAlignment(op_desc, align_shape, check_dim, input_orinal_shape)) {
     649              :     GELOGD("[%s] notask check dim alignment failed, dim = %lld.", op_desc->GetName().c_str(), check_dim);
     650              :     return false;
     651              :   }
     652              : 
     653              :   return true;
     654              : }
     655              : }  // namespace ge
        

Generated by: LCOV version 2.3.2-1