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
|