Line data Source code
1 : /**
2 : * Copyright (c) 2025 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/format_optimize/transop_without_reshape_fusion_pass.h"
12 : #include <algorithm>
13 : #include <memory>
14 : #include <sstream>
15 : #include <string>
16 : #include <atomic>
17 :
18 : #include "common/plugin/ge_make_unique_util.h"
19 : #include "framework/common/ge_inner_error_codes.h"
20 : #include "framework/common/framework_types_internal.h"
21 : #include "common/op/transop_util.h"
22 : #include "graph/compute_graph.h"
23 : #include "graph/debug/ge_attr_define.h"
24 : #include "graph/ge_tensor.h"
25 : #include "graph/op_desc.h"
26 : #include "graph/utils/graph_utils.h"
27 : #include "graph/utils/node_utils.h"
28 : #include "graph/utils/op_desc_utils.h"
29 : #include "graph/utils/type_utils.h"
30 : #include "graph/common/trans_op_creator.h"
31 : #include "api/gelib/gelib.h"
32 :
33 : namespace {
34 : const char *const kRemainNode = "node_remain";
35 : const int32_t kInvalidFusionOpCount = -1;
36 : const char *const kAttrNameSrcFormat = "src_format";
37 : const char *const kAttrNameDstFormat = "dst_format";
38 : } // namespace
39 :
40 : namespace ge {
41 : void TransOpWithoutReshapeFusionPass::SetRemainNode(
42 : const std::vector<std::pair<OutDataAnchorPtr, InDataAnchorPtr>> &nodes_anchor) {
43 : auto iter = nodes_anchor.begin();
44 : while (iter != nodes_anchor.end()) {
45 : auto in_anchor = iter->second;
46 : if (in_anchor == nullptr) {
47 : return;
48 : }
49 : auto in_node = in_anchor->GetOwnerNode();
50 : ++iter;
51 : if (in_node == nullptr) {
52 : return;
53 : }
54 : if (!IsTransOp(in_node)) {
55 : continue;
56 : }
57 :
58 : auto op_desc = in_node->GetOpDesc();
59 : if (op_desc == nullptr) {
60 : continue;
61 : }
62 : GELOGI("SetRemainNode node is %s", op_desc->GetName().c_str());
63 : GE_IF_BOOL_EXEC(!op_desc->SetExtAttr(kRemainNode, true),
64 : REPORT_INNER_ERR_MSG("E19999", "Set Attr:%s to op:%s(%s) failed", kRemainNode,
65 : op_desc->GetName().c_str(), op_desc->GetType().c_str());
66 : GELOGE(INTERNAL_ERROR, "[Set][Attr] %s to op:%s(%s) failed", kRemainNode,
67 : op_desc->GetName().c_str(), op_desc->GetType().c_str());
68 : return);
69 : auto out_ctrl_anchor = in_node->GetOutControlAnchor();
70 : if (out_ctrl_anchor != nullptr) {
71 : remain_out_control_anchors_.emplace(out_ctrl_anchor);
72 : for (const auto &peer_in_ctrl_anchor : out_ctrl_anchor->GetPeerInControlAnchors()) {
73 : remain_in_control_anchors_.emplace(peer_in_ctrl_anchor);
74 : }
75 : }
76 : }
77 : }
78 :
79 : bool TransOpWithoutReshapeFusionPass::IsFormatContinuous(const OutDataAnchorPtr &out_anchor,
80 : const InDataAnchorPtr &in_anchor) const {
81 : if ((out_anchor == nullptr) || (in_anchor == nullptr) || (in_anchor->GetOwnerNode() == nullptr) ||
82 : (out_anchor->GetOwnerNode() == nullptr)) {
83 : return false;
84 : }
85 : auto in_node = in_anchor->GetOwnerNode();
86 : GE_IF_BOOL_EXEC(in_node == nullptr,
87 : REPORT_INNER_ERR_MSG("E19999", "Param in_anchor's owner node is nullptr, check invalid");
88 : GELOGE(INTERNAL_ERROR, "[Check][Param]Param in_anchor's owner node is nullptr"); return false);
89 : auto in_op = in_node->GetOpDesc();
90 : auto out_owner_node = out_anchor->GetOwnerNode();
91 : GE_IF_BOOL_EXEC(out_owner_node == nullptr,
92 : REPORT_INNER_ERR_MSG("E19999", "Param out_anchor's owner node is nullptr, check invalid");
93 : GELOGE(INTERNAL_ERROR, "[Check][Param] Param out_anchor's owner node is nullptr"); return false);
94 : auto out_op = out_owner_node->GetOpDesc();
95 : GE_IF_BOOL_EXEC(in_op == nullptr,
96 : REPORT_INNER_ERR_MSG("E19999", "Param in_anchor's owner op_desc is nullptr, check invalid");
97 : GELOGE(INTERNAL_ERROR, "[Check][Param] Param in_anchor's owner op_desc is nullptr"); return false);
98 : GE_IF_BOOL_EXEC(out_op == nullptr,
99 : REPORT_INNER_ERR_MSG("E19999", "Param out_anchor's owner op_desc is nullptr, check invalid");
100 : GELOGE(INTERNAL_ERROR, "[Check][Param] Param out_anchor's owner op_desc is nullptr"); return false);
101 : auto in_op_desc = in_op->GetInputDescPtr(in_anchor->GetIdx());
102 : auto out_op_desc = out_op->GetOutputDescPtr(out_anchor->GetIdx());
103 : GE_IF_BOOL_EXEC(in_op_desc == nullptr,
104 : REPORT_INNER_ERR_MSG("E19999", "Param in_anchor corresponding tensor is nullptr, check invalid");
105 : GELOGE(INTERNAL_ERROR, "[Check][Param] Param in_anchor corresponding tensor is nullptr");
106 : return false);
107 : GE_IF_BOOL_EXEC(out_op_desc == nullptr,
108 : REPORT_INNER_ERR_MSG("E19999", "Param out_anchor corresponding tensor is nullptr, check invalid");
109 : GELOGE(INTERNAL_ERROR, "[Check][Param] Param out_anchor corresponding tensor is nullptr");
110 : return false);
111 : if (!ShapeEqualCheck(in_op_desc->GetShape(), out_op_desc->GetShape())) {
112 : GELOGD("Node %s(%s) output shape %s, node %s(%s) input shape %s, not continuous.", out_op->GetNamePtr(),
113 : out_op->GetTypePtr(), out_op_desc->GetShape().ToString().c_str(), in_op->GetNamePtr(), in_op->GetTypePtr(),
114 : in_op_desc->GetShape().ToString().c_str());
115 : return false;
116 : }
117 :
118 : if (in_op_desc->GetFormat() != out_op_desc->GetFormat()) {
119 : GELOGD("Node %s(%s) output format %s, node %s(%s) input format %s, not continuous.", out_op->GetNamePtr(),
120 : out_op->GetTypePtr(), TypeUtils::FormatToSerialString(out_op_desc->GetFormat()).c_str(), in_op->GetNamePtr(),
121 : in_op->GetTypePtr(), TypeUtils::FormatToSerialString(in_op_desc->GetFormat()).c_str());
122 : return false;
123 : }
124 :
125 : if (IsTransOp(in_node) && in_op->GetType() != CAST) {
126 : if (in_op_desc->GetFormat() == FORMAT_ND) {
127 : GELOGD("Node %s(%s) input format %s, not support fusion.", in_op->GetNamePtr(), in_op->GetTypePtr(),
128 : TypeUtils::FormatToSerialString(in_op_desc->GetFormat()).c_str());
129 : return false;
130 : }
131 :
132 : if (!FusionFormatSupport(in_op_desc->GetFormat())) {
133 : GELOGD("Node %s(%s) input format %s, not support fusion.", in_op->GetNamePtr(), in_op->GetTypePtr(),
134 : TypeUtils::FormatToSerialString(in_op_desc->GetFormat()).c_str());
135 : return false;
136 : }
137 : }
138 :
139 : return true;
140 : }
141 :
142 : // AxpyV2 (FP16 -> FP32)
143 : // |
144 : // CAST (FP16 -> FP32)
145 : // 修改背景:AxpyV2算子的原始输出dtype是BF16,在OpJudge阶段storage
146 : // shape被刷成FP32,被该pass认为两个node的输入输出type一致,将cast节点删除
147 : // FE在重型格式扩散时,由于cast不是aicore算子,无法扩散到AxpyV2节点,在该阶段FE会插入Trans_cast算子和Cast节点刚好对消
148 : // 如果该pass认为两个node的输入输出type一致,将cast节点删除,FE在重型格式扩散时,会将AxpyV2格式也设置为NZ格式,插入Trans_cast算子时无法和Cast节点对消
149 : bool TransOpWithoutReshapeFusionPass::IsTransOpDataTypeContinuous(const OutDataAnchorPtr &out_anchor,
150 : const InDataAnchorPtr &in_anchor) const {
151 : if ((out_anchor == nullptr) || (in_anchor == nullptr)) {
152 : return false;
153 : }
154 : const auto in_node = in_anchor->GetOwnerNodeBarePtr();
155 : if (in_node == nullptr) {
156 : return false;
157 : }
158 : if (!IsTransOp(in_node)) {
159 : return true;
160 : }
161 :
162 : const auto out_node = out_anchor->GetOwnerNodeBarePtr();
163 : if (out_node == nullptr) {
164 : return false;
165 : }
166 : const auto in_op_desc = in_node->GetOpDesc();
167 : if (in_op_desc == nullptr) {
168 : return false;
169 : }
170 : const auto out_op_desc = out_node->GetOpDesc();
171 : if (out_op_desc == nullptr) {
172 : return false;
173 : }
174 :
175 : // 转换链融合前需要确认数据类型连续性:当前数据边上游输出 dtype 必须等于下游 TransOp 输入 dtype。
176 : const auto input_desc = in_op_desc->GetInputDescPtr(in_anchor->GetIdx());
177 : const auto output_desc = out_op_desc->GetOutputDescPtr(out_anchor->GetIdx());
178 : if ((input_desc == nullptr) || (output_desc == nullptr)) {
179 : return false;
180 : }
181 : if (input_desc->GetDataType() == output_desc->GetDataType()) {
182 : return true;
183 : }
184 :
185 : GELOGD(
186 : "[Check][DataType] Trans op fusion is skipped, node:%s(%s), input idx:%d, input datatype:%s, "
187 : "prev node:%s(%s), output idx:%d, output datatype:%s.",
188 : in_op_desc->GetNamePtr(), in_op_desc->GetTypePtr(), in_anchor->GetIdx(),
189 : TypeUtils::DataTypeToSerialString(input_desc->GetDataType()).c_str(), out_op_desc->GetNamePtr(),
190 : out_op_desc->GetTypePtr(), out_anchor->GetIdx(),
191 : TypeUtils::DataTypeToSerialString(output_desc->GetDataType()).c_str());
192 : return false;
193 : }
194 :
195 : bool TransOpWithoutReshapeFusionPass::HasPrecisionLoss(const OutDataAnchorPtr &out_anchor,
196 : const InDataAnchorPtr &in_anchor) const {
197 : auto out_node = out_anchor->GetOwnerNode();
198 : GE_ASSERT_NOTNULL(out_node);
199 : auto in_node = in_anchor->GetOwnerNode();
200 : GE_ASSERT_NOTNULL(in_node);
201 : if (in_node->GetType() == CAST && TransOpUtil::IsPrecisionLoss(in_node)) {
202 : return true;
203 : }
204 : if (out_node->GetType() == CAST && TransOpUtil::IsPrecisionLoss(out_node)) {
205 : return true;
206 : }
207 : return false;
208 : }
209 :
210 : graphStatus TransOpWithoutReshapeFusionPass::IsTransposeNoNeedFusion(const Node *node, bool &no_need_fusion) const {
211 : no_need_fusion = false;
212 : if ((node->GetType() != TRANSPOSE) && (node->GetType() != TRANSPOSED)) {
213 : return GRAPH_SUCCESS;
214 : }
215 :
216 : GE_CHECK_NOTNULL(node->GetOpDesc());
217 : GE_ASSERT_NOTNULL(node->GetOpDesc()->GetInputDescPtr(0));
218 : auto input_format = node->GetOpDesc()->GetInputDescPtr(0)->GetFormat();
219 : GE_ASSERT_NOTNULL(node->GetOpDesc()->GetOutputDescPtr(0));
220 : auto output_format = node->GetOpDesc()->GetOutputDescPtr(0)->GetFormat();
221 : bool is_unknown = false;
222 : // No need to fusion when input and output format is same or is unknown shape
223 : if ((input_format == output_format) ||
224 : ((NodeUtils::GetNodeUnknownShapeStatus(*node, is_unknown) == GRAPH_SUCCESS) && is_unknown)) {
225 : GELOGD("Abandoned Fusion node %s(%s) is unknown shape.", node->GetNamePtr(), node->GetTypePtr());
226 : no_need_fusion = true;
227 : }
228 : return GRAPH_SUCCESS;
229 : }
230 :
231 : graphStatus TransOpWithoutReshapeFusionPass::NeedRemainNode(const OutDataAnchorPtr &out_anchor,
232 : const InDataAnchorPtr &in_anchor, bool &need_remain) const {
233 : need_remain = false;
234 : GE_CHECK_NOTNULL(in_anchor);
235 : auto in_node = in_anchor->GetOwnerNodeBarePtr();
236 : GE_CHECK_NOTNULL(in_node);
237 : if (in_node->GetType() == RESHAPE) {
238 : GELOGD("Abandoned Fusion node %s type: RESHAPE", in_node->GetNamePtr());
239 : need_remain = true;
240 : return GRAPH_SUCCESS;
241 : }
242 :
243 : GE_CHK_STATUS_RET(IsTransposeNoNeedFusion(in_node, need_remain));
244 : if (need_remain) {
245 : return GRAPH_SUCCESS;
246 : }
247 :
248 : GE_CHECK_NOTNULL(out_anchor);
249 : auto out_node = out_anchor->GetOwnerNodeBarePtr();
250 : GE_CHECK_NOTNULL(out_node);
251 : if (!IsFormatContinuous(out_anchor, in_anchor)) {
252 : GELOGD("Abandoned Fusion node %s(%s) and node %s(%s) format is uncontinuous or not support.",
253 : out_node->GetNamePtr(), out_node->GetTypePtr(), in_node->GetNamePtr(), in_node->GetTypePtr());
254 : need_remain = true;
255 : return GRAPH_SUCCESS;
256 : }
257 :
258 : if (!IsTransOpDataTypeContinuous(out_anchor, in_anchor)) {
259 : GELOGD("Abandoned Fusion node %s(%s) input datatype is uncontinuous.", in_node->GetNamePtr(),
260 : in_node->GetTypePtr());
261 : need_remain = true;
262 : return GRAPH_SUCCESS;
263 : }
264 :
265 : if (HasPrecisionLoss(out_anchor, in_anchor)) {
266 : GELOGD("Abandoned Fusion node %s(%s) and node %s(%s) has precision loss.", out_node->GetNamePtr(),
267 : out_node->GetTypePtr(), in_node->GetNamePtr(), in_node->GetTypePtr());
268 : need_remain = true;
269 : }
270 : return GRAPH_SUCCESS;
271 : }
272 :
273 : graphStatus TransOpWithoutReshapeFusionPass::GetSubGraphNodesInfo(const size_t index, bool &has_remain_node,
274 : int32_t &transop_num_count,
275 : std::vector<NodePtr> &sub_graph_nodes) const {
276 : has_remain_node = false;
277 : transop_num_count = 0;
278 : auto nodes_anchor = sub_graph_anchors_[index];
279 : auto iter = nodes_anchor.begin();
280 : auto first_out_anchor = iter->first;
281 : if (first_out_anchor == nullptr) {
282 : return GRAPH_SUCCESS;
283 : }
284 : sub_graph_nodes.push_back(first_out_anchor->GetOwnerNode());
285 :
286 : while (iter != nodes_anchor.end()) {
287 : auto in_anchor = iter->second;
288 : bool need_remain = false;
289 : GE_CHK_STATUS_RET(NeedRemainNode(iter->first, in_anchor, need_remain));
290 : if (need_remain) {
291 : has_remain_node = true;
292 : break;
293 : }
294 :
295 : auto in_node = in_anchor->GetOwnerNode();
296 : GE_CHECK_NOTNULL(in_node);
297 : sub_graph_nodes.push_back(in_node);
298 : if (IsTransOp(in_node)) {
299 : ++transop_num_count;
300 : }
301 : ++iter;
302 : }
303 : return GRAPH_SUCCESS;
304 : }
305 :
306 : graphStatus TransOpWithoutReshapeFusionPass::GetSubGraphNodesInfo() {
307 : std::vector<bool> sub_graph_has_reshape_node(sub_graph_anchors_.size(), false);
308 : std::vector<int32_t> transop_num_count(sub_graph_anchors_.size(), 0);
309 : std::vector<std::vector<NodePtr>> sub_graph_nodes(sub_graph_anchors_.size());
310 : for (size_t i = 0; i < sub_graph_anchors_.size(); ++i) {
311 : bool has_remain_node = false;
312 : int32_t current_transop_num_count = 0;
313 : std::vector<NodePtr> nodes_tmp;
314 : GE_CHK_STATUS_RET(GetSubGraphNodesInfo(i, has_remain_node, current_transop_num_count, nodes_tmp));
315 : sub_graph_has_reshape_node[i] = has_remain_node;
316 : transop_num_count[i] = current_transop_num_count;
317 : sub_graph_nodes[i].swap(nodes_tmp);
318 : if (sub_graph_has_reshape_node[i]) {
319 : SetRemainNode(sub_graph_anchors_[i]);
320 : }
321 : }
322 :
323 : sub_graph_has_reshape_node_.swap(sub_graph_has_reshape_node);
324 : transop_num_count_.swap(transop_num_count);
325 : sub_graph_nodes_.swap(sub_graph_nodes);
326 : return GRAPH_SUCCESS;
327 : }
328 :
329 : void TransOpWithoutReshapeFusionPass::GetOutDataPeerInControlAnchors(
330 : const size_t index, std::vector<std::vector<InControlAnchorPtr>> &out_data_peer_in_control_anchors) {
331 : // The caller guarantees that the index is legal.
332 : for (size_t j = 1; j < sub_graph_anchors_[index].size(); ++j) {
333 : auto nodes_anchor = sub_graph_anchors_[index][j];
334 : auto out_data_anchor = nodes_anchor.first;
335 : GE_CHECK_NOTNULL_JUST_RETURN(out_data_anchor);
336 : for (const auto &peer_in_control_anchor : out_data_anchor->GetPeerInControlAnchors()) {
337 : GE_CHECK_NOTNULL_JUST_RETURN(peer_in_control_anchor);
338 : auto peer_node = peer_in_control_anchor->GetOwnerNode();
339 : if (peer_node == nullptr) {
340 : continue;
341 : }
342 : auto iter = std::find(sub_graph_nodes_[index].begin(), sub_graph_nodes_[index].end(), peer_node);
343 : if (iter == sub_graph_nodes_[index].end()) {
344 : out_data_peer_in_control_anchors[index].push_back(peer_in_control_anchor);
345 : } else {
346 : sub_graph_has_out_data_peer_in_control_edge_[index] = true;
347 : }
348 : }
349 : }
350 : }
351 :
352 : void TransOpWithoutReshapeFusionPass::GetInControlPeerOutControlAnchors(
353 : const size_t index, std::vector<std::vector<OutControlAnchorPtr>> &in_control_peer_out_control_anchors) {
354 : // The caller guarantees that the index is legal.
355 : for (size_t j = 1; j < (sub_graph_nodes_[index].size() - 1); ++j) {
356 : auto node = sub_graph_nodes_[index][j];
357 : GE_CHECK_NOTNULL_JUST_RETURN(node);
358 : auto in_control_anchor = node->GetInControlAnchor();
359 : if (in_control_anchor == nullptr) {
360 : continue;
361 : }
362 :
363 : for (const auto &peer_out_anchor : in_control_anchor->GetPeerOutControlAnchors()) {
364 : GE_CHECK_NOTNULL_JUST_RETURN(peer_out_anchor);
365 : auto peer_node = peer_out_anchor->GetOwnerNode();
366 : if (peer_node == nullptr) {
367 : continue;
368 : }
369 : auto iter = std::find(sub_graph_nodes_[index].begin(), sub_graph_nodes_[index].end(), peer_node);
370 : if (iter == sub_graph_nodes_[index].end()) {
371 : in_control_peer_out_control_anchors[index].push_back(peer_out_anchor);
372 : } else {
373 : sub_graph_has_control_edge_[index] = true;
374 : }
375 : }
376 : }
377 : }
378 :
379 : void TransOpWithoutReshapeFusionPass::GetOutControlPeerAnchors(
380 : const size_t index, std::vector<std::vector<InControlAnchorPtr>> &out_control_peer_in_control_anchors,
381 : std::vector<std::vector<InDataAnchorPtr>> &out_control_peer_in_data_anchors) {
382 : for (size_t j = 0; j < sub_graph_nodes_[index].size() - 1; ++j) {
383 : auto node = sub_graph_nodes_[index][j];
384 : GE_CHECK_NOTNULL_JUST_RETURN(node);
385 : auto out_control_anchor = node->GetOutControlAnchor();
386 : GE_CHECK_NOTNULL_JUST_RETURN(out_control_anchor);
387 :
388 : for (const auto &peer_in_anchor : out_control_anchor->GetPeerInControlAnchors()) {
389 : GE_CHECK_NOTNULL_JUST_RETURN(peer_in_anchor);
390 : auto peer_node = peer_in_anchor->GetOwnerNode();
391 : if (peer_node == nullptr) {
392 : continue;
393 : }
394 : auto iter = std::find(sub_graph_nodes_[index].begin(), sub_graph_nodes_[index].end(), peer_node);
395 : if (iter == sub_graph_nodes_[index].end()) {
396 : /*
397 : opA
398 : |
399 : trans1 ---->opD
400 : | |
401 : trans2<-----opE
402 : 临时方案:A-B-C-D若此链路上A所有控制输出节点,都被融合后链路的尾部算子控制,有控制边下移成环的风险。
403 : 转换算子一般为框架成图后插入,且insertbefore的场景的输出控制才重要。
404 : 因此认为链路头部的输出控制不重要,为避免成环,不处理头部转换算子的控制边
405 : 正式方案:控制边链接时需要遍历图,判断有成环风险后放弃融合。
406 : */
407 : if (j > 1U) {
408 : out_control_peer_in_control_anchors[index].push_back(peer_in_anchor);
409 : }
410 : } else {
411 : sub_graph_has_control_edge_[index] = true;
412 : }
413 : }
414 :
415 : for (const auto &peer_in_anchor : out_control_anchor->GetPeerInDataAnchors()) {
416 : GE_CHECK_NOTNULL_JUST_RETURN(peer_in_anchor);
417 : auto peer_node = peer_in_anchor->GetOwnerNode();
418 : if (peer_node == nullptr) {
419 : continue;
420 : }
421 : auto iter = std::find(sub_graph_nodes_[index].begin(), sub_graph_nodes_[index].end(), peer_node);
422 : if (iter == sub_graph_nodes_[index].end()) {
423 : if (j > 0) {
424 : out_control_peer_in_data_anchors[index].push_back(peer_in_anchor);
425 : }
426 : } else {
427 : sub_graph_has_control_edge_[index] = true;
428 : }
429 : }
430 : }
431 : }
432 :
433 : void TransOpWithoutReshapeFusionPass::GetControlAnchors() {
434 : std::vector<std::vector<OutControlAnchorPtr>> in_control_peer_out_control_anchors(sub_graph_nodes_.size());
435 : std::vector<std::vector<InControlAnchorPtr>> out_control_peer_in_control_anchors(sub_graph_nodes_.size());
436 : std::vector<std::vector<InDataAnchorPtr>> out_control_peer_in_data_anchors(sub_graph_nodes_.size());
437 : std::vector<std::vector<InControlAnchorPtr>> out_data_peer_in_control_anchors(sub_graph_nodes_.size());
438 : std::vector<bool> sub_graph_has_control_edge(sub_graph_nodes_.size(), false);
439 : sub_graph_has_control_edge_.swap(sub_graph_has_control_edge);
440 : std::vector<bool> sub_graph_has_out_data_peer_in_control_edge(sub_graph_nodes_.size(), false);
441 : sub_graph_has_out_data_peer_in_control_edge_.swap(sub_graph_has_out_data_peer_in_control_edge);
442 : for (size_t i = 0; i < sub_graph_nodes_.size(); ++i) {
443 : if (sub_graph_has_reshape_node_[i]) {
444 : continue;
445 : }
446 :
447 : GetOutDataPeerInControlAnchors(i, out_data_peer_in_control_anchors);
448 :
449 : GetInControlPeerOutControlAnchors(i, in_control_peer_out_control_anchors);
450 :
451 : GetOutControlPeerAnchors(i, out_control_peer_in_control_anchors, out_control_peer_in_data_anchors);
452 : }
453 :
454 : in_control_peer_out_control_anchors_.swap(in_control_peer_out_control_anchors);
455 : out_control_peer_in_control_anchors_.swap(out_control_peer_in_control_anchors);
456 : out_control_peer_in_data_anchors_.swap(out_control_peer_in_data_anchors);
457 : out_data_peer_in_control_anchors_.swap(out_data_peer_in_control_anchors);
458 : }
459 :
460 : void TransOpWithoutReshapeFusionPass::EraseInvalidAnchorsPair() {
461 : auto sub_graph_iter = sub_graph_anchors_.begin();
462 : while (sub_graph_iter != sub_graph_anchors_.end()) {
463 : if (sub_graph_iter->size() <= 1) {
464 : sub_graph_iter = sub_graph_anchors_.erase(sub_graph_iter);
465 : } else {
466 : ++sub_graph_iter;
467 : }
468 : }
469 : }
470 :
471 : void TransOpWithoutReshapeFusionPass::UpdateOutputName(const OutDataAnchorPtr &out_anchor,
472 : const InDataAnchorPtr &old_peer_in_anchor,
473 : const NodePtr &in_owner_node) const {
474 : if ((out_anchor == nullptr) || (old_peer_in_anchor == nullptr) || (in_owner_node == nullptr)) {
475 : GELOGI("out_anchor or old_peer_in_anchor or in_owner_node is nullptr");
476 : return;
477 : }
478 : auto out_owner_node = out_anchor->GetOwnerNode();
479 : GE_CHECK_NOTNULL_JUST_RETURN(out_owner_node);
480 : GE_CHECK_NOTNULL_JUST_RETURN(old_peer_in_anchor->GetOwnerNode());
481 : auto old_peer_in_name = old_peer_in_anchor->GetOwnerNode()->GetName();
482 : auto output_op = out_owner_node->GetOpDesc();
483 : GE_CHECK_NOTNULL_JUST_RETURN(output_op);
484 : auto output_names = output_op->GetAllOutputName();
485 : const auto old_peer_in_name_iter = output_names.find(old_peer_in_name);
486 : if (old_peer_in_name_iter != output_names.end()) {
487 : output_names.erase(old_peer_in_name_iter);
488 : }
489 : output_names[in_owner_node->GetName()] = out_anchor->GetIdx();
490 : if (!output_op->UpdateOutputName(output_names)) {
491 : GELOGW("output_op UpdateOutputName failed");
492 : }
493 : }
494 :
495 : void TransOpWithoutReshapeFusionPass::UpdateInputName(const OutDataAnchorPtr &old_peer_out_anchor,
496 : const InDataAnchorPtr &in_anchor,
497 : const NodePtr &out_owner_node) const {
498 : if ((old_peer_out_anchor == nullptr) || (in_anchor == nullptr) || (out_owner_node == nullptr)) {
499 : GELOGI("old_peer_out_anchor or in_anchor or out_owner_node is nullptr");
500 : return;
501 : }
502 : auto old_node = old_peer_out_anchor->GetOwnerNode();
503 : GE_CHECK_NOTNULL_JUST_RETURN(old_node);
504 : auto old_peer_out_name = old_node->GetName();
505 : auto in_owner_node = in_anchor->GetOwnerNode();
506 : GE_CHECK_NOTNULL_JUST_RETURN(in_owner_node);
507 : auto input_op = in_owner_node->GetOpDesc();
508 : GE_CHECK_NOTNULL_JUST_RETURN(input_op);
509 : auto input_names = input_op->GetAllInputName();
510 : const auto old_peer_out_name_iter = input_names.find(old_peer_out_name);
511 : if (old_peer_out_name_iter != input_names.end()) {
512 : input_names.erase(old_peer_out_name_iter);
513 : }
514 : input_names[out_owner_node->GetName()] = in_anchor->GetIdx();
515 : input_op->UpdateInputName(input_names);
516 : }
517 :
518 : graphStatus TransOpWithoutReshapeFusionPass::RelinkSubGraphControlEdges(
519 : const std::pair<OutDataAnchorPtr, InDataAnchorPtr> &begin_anchors_pair,
520 : const std::pair<OutDataAnchorPtr, InDataAnchorPtr> &end_anchors_pair, const int32_t index) {
521 : auto out_anchor = begin_anchors_pair.first;
522 : GE_CHECK_NOTNULL(out_anchor);
523 : auto out_owner_node = out_anchor->GetOwnerNode();
524 : GE_CHECK_NOTNULL(out_owner_node);
525 : auto in_anchor = end_anchors_pair.second;
526 : GE_CHECK_NOTNULL(in_anchor);
527 : auto in_owner_node = in_anchor->GetOwnerNode();
528 : GE_CHECK_NOTNULL(in_owner_node);
529 : if (sub_graph_has_control_edge_[index]) {
530 : GELOGI("add control edge.src:%s, dst:%s", out_owner_node->GetName().c_str(), in_owner_node->GetName().c_str());
531 : if (GraphUtils::AddEdge(out_owner_node->GetOutControlAnchor(), in_owner_node->GetInControlAnchor()) !=
532 : GRAPH_SUCCESS) {
533 : REPORT_INNER_ERR_MSG("E19999", "Add control edge between op:%s(%s) and op:%s(%s) failed",
534 : out_owner_node->GetName().c_str(), out_owner_node->GetType().c_str(),
535 : in_owner_node->GetName().c_str(), in_owner_node->GetType().c_str());
536 : GELOGE(GRAPH_FAILED, "[Add][ControlEdge] between op:%s(%s) and op:%s(%s) failed",
537 : out_owner_node->GetName().c_str(), out_owner_node->GetType().c_str(), in_owner_node->GetName().c_str(),
538 : in_owner_node->GetType().c_str());
539 : return GRAPH_FAILED;
540 : }
541 : }
542 :
543 : if (sub_graph_has_out_data_peer_in_control_edge_[index]) {
544 : GELOGI("add out data 2 in control edge.src:%s, dst:%s", out_owner_node->GetName().c_str(),
545 : in_owner_node->GetName().c_str());
546 : if (GraphUtils::AddEdge(out_anchor, in_owner_node->GetInControlAnchor()) != GRAPH_SUCCESS) {
547 : REPORT_INNER_ERR_MSG("E19999", "Add control edge between op:%s(%s) and op:%s(%s) failed",
548 : out_owner_node->GetName().c_str(), out_owner_node->GetType().c_str(),
549 : in_owner_node->GetName().c_str(), in_owner_node->GetType().c_str());
550 : GELOGE(GRAPH_FAILED, "[Add][ControlEdge] between op:%s(%s) and op:%s(%s) failed",
551 : out_owner_node->GetName().c_str(), out_owner_node->GetType().c_str(), in_owner_node->GetName().c_str(),
552 : in_owner_node->GetType().c_str());
553 : return GRAPH_FAILED;
554 : }
555 : }
556 : return GRAPH_SUCCESS;
557 : }
558 :
559 : graphStatus TransOpWithoutReshapeFusionPass::RelinkControlEdgesWhenDescNotChanged(
560 : const std::pair<OutDataAnchorPtr, InDataAnchorPtr> &begin_anchors_pair,
561 : const std::pair<OutDataAnchorPtr, InDataAnchorPtr> &end_anchors_pair, const int32_t index) {
562 : if (RelinkSubGraphControlEdges(begin_anchors_pair, end_anchors_pair, index) != GRAPH_SUCCESS) {
563 : return GRAPH_FAILED;
564 : }
565 :
566 : auto out_anchor = begin_anchors_pair.first;
567 : GE_CHECK_NOTNULL(out_anchor);
568 : auto out_owner_node = out_anchor->GetOwnerNode();
569 : GE_CHECK_NOTNULL(out_owner_node);
570 : auto in_anchor = end_anchors_pair.second;
571 : GE_CHECK_NOTNULL(in_anchor);
572 : auto in_owner_node = in_anchor->GetOwnerNode();
573 : GE_CHECK_NOTNULL(in_owner_node);
574 : // cannot remove old control edge
575 : for (const auto &peer_in_anchor : out_control_peer_in_control_anchors_[index]) {
576 : GE_CHECK_NOTNULL(peer_in_anchor);
577 : if (remain_in_control_anchors_.count(peer_in_anchor) > 0) {
578 : continue;
579 : }
580 : GELOGI("add control edge.src:%s, dst:%s, dst idx:%d", out_owner_node->GetName().c_str(),
581 : peer_in_anchor->GetOwnerNode()->GetName().c_str(), peer_in_anchor->GetIdx());
582 : if (GraphUtils::AddEdge(out_owner_node->GetOutControlAnchor(), peer_in_anchor) != GRAPH_SUCCESS) {
583 : REPORT_INNER_ERR_MSG("E19999", "Add control edge between op:%s(%s) and op:%s(%s) failed",
584 : out_owner_node->GetName().c_str(), out_owner_node->GetType().c_str(),
585 : peer_in_anchor->GetOwnerNode()->GetName().c_str(),
586 : peer_in_anchor->GetOwnerNode()->GetType().c_str());
587 : GELOGE(GRAPH_FAILED, "[Add]ControlEdge] between op:%s(%s) and op:%s(%s) failed",
588 : out_owner_node->GetName().c_str(), out_owner_node->GetType().c_str(),
589 : peer_in_anchor->GetOwnerNode()->GetName().c_str(), peer_in_anchor->GetOwnerNode()->GetType().c_str());
590 : return GRAPH_FAILED;
591 : }
592 : }
593 :
594 : for (const auto &peer_out_anchor : in_control_peer_out_control_anchors_[index]) {
595 : GE_CHECK_NOTNULL(peer_out_anchor);
596 : if (remain_out_control_anchors_.count(peer_out_anchor) > 0) {
597 : continue;
598 : }
599 : GELOGI("add control edge.src:%s, src idx:%d, dst:%s", peer_out_anchor->GetOwnerNode()->GetName().c_str(),
600 : peer_out_anchor->GetIdx(), in_owner_node->GetName().c_str());
601 : if (GraphUtils::AddEdge(peer_out_anchor, in_owner_node->GetInControlAnchor()) != GRAPH_SUCCESS) {
602 : REPORT_INNER_ERR_MSG("E19999", "Add control edge between op:%s(%s) and op:%s(%s) failed",
603 : peer_out_anchor->GetOwnerNode()->GetName().c_str(),
604 : peer_out_anchor->GetOwnerNode()->GetType().c_str(), in_owner_node->GetName().c_str(),
605 : in_owner_node->GetType().c_str());
606 : GELOGE(GRAPH_FAILED, "[Add]ControlEdge] between op:%s(%s) and op:%s(%s) failed",
607 : peer_out_anchor->GetOwnerNode()->GetName().c_str(), peer_out_anchor->GetOwnerNode()->GetType().c_str(),
608 : in_owner_node->GetName().c_str(), in_owner_node->GetType().c_str());
609 : return GRAPH_FAILED;
610 : }
611 : }
612 :
613 : for (const auto &peer_in_anchor : out_control_peer_in_data_anchors_[index]) {
614 : GE_CHECK_NOTNULL(peer_in_anchor);
615 : GELOGI("add out control 2 in data edge.src:%s, dst:%s, dst idx:%d", out_owner_node->GetName().c_str(),
616 : peer_in_anchor->GetOwnerNode()->GetName().c_str(), peer_in_anchor->GetIdx());
617 : if (GraphUtils::AddEdge(out_owner_node->GetOutControlAnchor(), peer_in_anchor) != GRAPH_SUCCESS) {
618 : REPORT_INNER_ERR_MSG("E19999", "Add control edge between op:%s(%s) and op:%s(%s) failed",
619 : out_owner_node->GetName().c_str(), out_owner_node->GetType().c_str(),
620 : peer_in_anchor->GetOwnerNode()->GetName().c_str(),
621 : peer_in_anchor->GetOwnerNode()->GetType().c_str());
622 : GELOGE(GRAPH_FAILED, "[Add]ControlEdge] between op:%s(%s) and op:%s(%s) failed",
623 : out_owner_node->GetName().c_str(), out_owner_node->GetType().c_str(),
624 : peer_in_anchor->GetOwnerNode()->GetName().c_str(), peer_in_anchor->GetOwnerNode()->GetType().c_str());
625 : return GRAPH_FAILED;
626 : }
627 : }
628 :
629 : for (const auto &peer_in_anchor : out_data_peer_in_control_anchors_[index]) {
630 : GE_CHECK_NOTNULL(peer_in_anchor);
631 : GELOGI("add out data 2 in control edge.src:%s, dst:%s, dst idx:%d", out_owner_node->GetName().c_str(),
632 : peer_in_anchor->GetOwnerNode()->GetName().c_str(), peer_in_anchor->GetIdx());
633 : if (GraphUtils::AddEdge(out_anchor, peer_in_anchor) != GRAPH_SUCCESS) {
634 : REPORT_INNER_ERR_MSG("E19999", "Add control edge between op:%s(%s) and op:%s(%s) failed",
635 : out_owner_node->GetName().c_str(), out_owner_node->GetType().c_str(),
636 : peer_in_anchor->GetOwnerNode()->GetName().c_str(),
637 : peer_in_anchor->GetOwnerNode()->GetType().c_str());
638 : GELOGE(GRAPH_FAILED, "[Add]ControlEdge] between op:%s(%s) and op:%s(%s) failed",
639 : out_owner_node->GetName().c_str(), out_owner_node->GetType().c_str(),
640 : peer_in_anchor->GetOwnerNode()->GetName().c_str(), peer_in_anchor->GetOwnerNode()->GetType().c_str());
641 : return GRAPH_FAILED;
642 : }
643 : }
644 : return GRAPH_SUCCESS;
645 : }
646 :
647 : graphStatus TransOpWithoutReshapeFusionPass::RelinkNodesWhenDescNotChanged(
648 : const std::pair<OutDataAnchorPtr, InDataAnchorPtr> &begin_anchors_pair,
649 : const std::pair<OutDataAnchorPtr, InDataAnchorPtr> &end_anchors_pair, const int32_t index) {
650 : auto out_anchor = begin_anchors_pair.first;
651 : GE_CHECK_NOTNULL(out_anchor);
652 : auto out_owner_node = out_anchor->GetOwnerNode();
653 : GE_CHECK_NOTNULL(out_owner_node);
654 : auto in_anchor = end_anchors_pair.second;
655 : GE_CHECK_NOTNULL(in_anchor);
656 : auto in_owner_node = in_anchor->GetOwnerNode();
657 : GE_CHECK_NOTNULL(in_owner_node);
658 : GELOGI("remove edge.src %s, src idx:%d, dst:%s, dst idx:%d",
659 : end_anchors_pair.first->GetOwnerNode()->GetName().c_str(), end_anchors_pair.first->GetIdx(),
660 : in_owner_node->GetName().c_str(), in_anchor->GetIdx());
661 : GE_CHK_STATUS_RET(GraphUtils::RemoveEdge(end_anchors_pair.first, in_anchor),
662 : "[Remove][Edge] between %s(%s)(index:%d) and %s(%s)(index:%d) failed",
663 : out_owner_node->GetName().c_str(), out_owner_node->GetType().c_str(), out_anchor->GetIdx(),
664 : in_owner_node->GetName().c_str(), in_owner_node->GetType().c_str(), in_anchor->GetIdx());
665 : GELOGI("relink node.src node:%s, src idx:%d, dst node:%s, dst idx:%d", out_owner_node->GetName().c_str(),
666 : out_anchor->GetIdx(), in_owner_node->GetName().c_str(), in_anchor->GetIdx());
667 : if (GraphUtils::AddEdge(out_anchor, in_anchor) != GRAPH_SUCCESS) {
668 : REPORT_INNER_ERR_MSG("E19999", "Add edge between op:%s(%s)(index:%d) and op:%s(%s)(index:%d) failed",
669 : out_owner_node->GetName().c_str(), out_owner_node->GetType().c_str(), out_anchor->GetIdx(),
670 : in_owner_node->GetName().c_str(), in_owner_node->GetType().c_str(), in_anchor->GetIdx());
671 : GELOGE(GRAPH_FAILED, "[Add][Edge] between op:%s(%s)(index:%d) and op:%s(%s)(index:%d) failed",
672 : out_owner_node->GetName().c_str(), out_owner_node->GetType().c_str(), out_anchor->GetIdx(),
673 : in_owner_node->GetName().c_str(), in_owner_node->GetType().c_str(), in_anchor->GetIdx());
674 : return GRAPH_FAILED;
675 : } else {
676 : auto old_peer_in_anchor = begin_anchors_pair.second;
677 : UpdateOutputName(out_anchor, old_peer_in_anchor, in_owner_node);
678 :
679 : auto old_peer_out_anchor = end_anchors_pair.first;
680 : UpdateInputName(old_peer_out_anchor, in_anchor, out_owner_node);
681 : }
682 :
683 : return RelinkControlEdgesWhenDescNotChanged(begin_anchors_pair, end_anchors_pair, index);
684 : }
685 :
686 : OpDescPtr TransOpWithoutReshapeFusionPass::GetFormatTransferOp(const GeTensorDesc &format_trans_input_desc,
687 : const GeTensorDesc &format_trans_output_desc) const {
688 : static std::atomic_long atomic_fusion_format_transfer_op_count(1);
689 : auto fusion_format_transfer_op_count = atomic_fusion_format_transfer_op_count.fetch_add(1);
690 :
691 : std::stringstream format_transfer_op_name;
692 : format_transfer_op_name << "fusion_format_transfer_" << fusion_format_transfer_op_count;
693 : OpDescPtr format_transfer_op = TransOpCreator::CreateTransDataOp(format_transfer_op_name.str(),
694 : format_trans_input_desc, format_trans_output_desc);
695 : if (format_transfer_op == nullptr) {
696 : GELOGW("[New][OpDesc] transdata failed");
697 : return nullptr;
698 : }
699 :
700 : GE_IF_BOOL_EXEC(!AttrUtils::SetInt(format_transfer_op, ATTR_NAME_INPUT_FORMAT,
701 : static_cast<int64_t>(format_trans_input_desc.GetFormat())),
702 : REPORT_INNER_ERR_MSG("E19999", "Set Attr:%s to op:%s(%s) failed", ATTR_NAME_INPUT_FORMAT.c_str(),
703 : format_transfer_op->GetName().c_str(), format_transfer_op->GetType().c_str());
704 : GELOGE(INTERNAL_ERROR, "[Set][Attr] %s to op:%s(%s) failed", ATTR_NAME_INPUT_FORMAT.c_str(),
705 : format_transfer_op->GetName().c_str(), format_transfer_op->GetType().c_str());
706 : return nullptr);
707 : GE_IF_BOOL_EXEC(!AttrUtils::SetInt(format_transfer_op, ATTR_NAME_OUTPUT_FORMAT,
708 : static_cast<int64_t>(format_trans_output_desc.GetFormat())),
709 : REPORT_INNER_ERR_MSG("E19999", "Set Attr:%s to op:%s(%s) failed", ATTR_NAME_OUTPUT_FORMAT.c_str(),
710 : format_transfer_op->GetName().c_str(), format_transfer_op->GetType().c_str());
711 : GELOGE(INTERNAL_ERROR, "[Set][Attr] %s to op:%s(%s) failed", ATTR_NAME_OUTPUT_FORMAT.c_str(),
712 : format_transfer_op->GetName().c_str(), format_transfer_op->GetType().c_str());
713 : return nullptr);
714 :
715 : return format_transfer_op;
716 : }
717 :
718 : OpDescPtr TransOpWithoutReshapeFusionPass::GetCastOp(const GeTensorDesc &cast_input_desc,
719 : const GeTensorDesc &cast_output_desc) const {
720 : static std::atomic_long atomic_fusion_cast_op_count(1);
721 : auto fusion_cast_op_count = atomic_fusion_cast_op_count.fetch_add(1);
722 :
723 : std::stringstream cast_op_name;
724 : cast_op_name << "fusion_cast_op_" << fusion_cast_op_count;
725 : auto node_op = ge::OperatorFactory::CreateOperator(cast_op_name.str().c_str(), CAST);
726 : auto cast_op = ge::OpDescUtils::GetOpDescFromOperator(node_op);
727 : node_op.BreakConnect();
728 : if (cast_op == nullptr) {
729 : REPORT_INNER_ERR_MSG("E19999", "Create operator:%s(%s) failed", cast_op_name.str().c_str(), CAST);
730 : GELOGE(INTERNAL_ERROR, "[Create][Operator] %s(%s) failed", cast_op_name.str().c_str(), CAST);
731 : return nullptr;
732 : }
733 : const int32_t default_input_index = 0;
734 : const int32_t default_output_index = 0;
735 : if (cast_op->GetInputsSize() == 0) {
736 : GE_IF_BOOL_EXEC(cast_op->AddInputDesc(cast_input_desc) != GRAPH_SUCCESS,
737 : REPORT_INNER_ERR_MSG("E19999", "Add input desc to op:%s(%s) failed", cast_op->GetName().c_str(),
738 : cast_op->GetType().c_str());
739 : GELOGE(INTERNAL_ERROR, "[Add][InputDesc] to op:%s(%s) failed", cast_op->GetName().c_str(),
740 : cast_op->GetType().c_str());
741 : return nullptr);
742 : } else {
743 : GE_IF_BOOL_EXEC(cast_op->UpdateInputDesc(default_input_index, cast_input_desc) != GRAPH_SUCCESS,
744 : REPORT_INNER_ERR_MSG("E19999", "Update input:%d desc of op:%s(%s) failed", default_input_index,
745 : cast_op->GetName().c_str(), cast_op->GetType().c_str());
746 : GELOGE(INTERNAL_ERROR, "[Update][InputDesc] of op:%s(%s) failed, input index:%d",
747 : cast_op->GetName().c_str(), cast_op->GetType().c_str(), default_input_index);
748 : return nullptr);
749 : }
750 :
751 : if (cast_op->GetOutputsSize() == 0) {
752 : GE_IF_BOOL_EXEC(cast_op->AddOutputDesc(cast_output_desc) != GRAPH_SUCCESS,
753 : REPORT_INNER_ERR_MSG("E19999", "Add output desc to op:%s(%s) failed", cast_op->GetName().c_str(),
754 : cast_op->GetType().c_str());
755 : GELOGE(INTERNAL_ERROR, "[Add][OutputDesc] to op:%s(%s) failed", cast_op->GetName().c_str(),
756 : cast_op->GetType().c_str());
757 : return nullptr);
758 : } else {
759 : GE_IF_BOOL_EXEC(cast_op->UpdateOutputDesc(default_output_index, cast_output_desc) != GRAPH_SUCCESS,
760 : REPORT_INNER_ERR_MSG("E19999", "Update output:%d desc of op:%s(%s) failed", default_output_index,
761 : cast_op->GetName().c_str(), cast_op->GetType().c_str());
762 : GELOGE(INTERNAL_ERROR, "[Update][OutputDesc] of op:%s(%s) failed, output index:%d",
763 : cast_op->GetName().c_str(), cast_op->GetType().c_str(), default_output_index);
764 : return nullptr);
765 : }
766 :
767 : if (!AttrUtils::SetInt(cast_op, CAST_ATTR_DST_TYPE, static_cast<int64_t>(cast_output_desc.GetDataType()))) {
768 : REPORT_INNER_ERR_MSG("E19999", "Set Attr:%s to op:%s(%s) failed", CAST_ATTR_DST_TYPE.c_str(),
769 : cast_op->GetName().c_str(), cast_op->GetType().c_str());
770 : GELOGE(INTERNAL_ERROR, "[Set][Attr] %s to op:%s(%s) failed", CAST_ATTR_DST_TYPE.c_str(), cast_op->GetName().c_str(),
771 : cast_op->GetType().c_str());
772 : return nullptr;
773 : }
774 : return cast_op;
775 : }
776 :
777 : bool TransOpWithoutReshapeFusionPass::InsertCastFirstCheck(const GeTensorDesc &out_desc,
778 : const GeTensorDesc &in_desc) const {
779 : return (out_desc.GetDataType() != in_desc.GetDataType()) && (out_desc.GetDataType() != DT_FLOAT16) &&
780 : (in_desc.GetDataType() == DT_FLOAT16);
781 : }
782 :
783 : void TransOpWithoutReshapeFusionPass::GetFormatTransferDesc(const GeTensorDesc &out_desc, const GeTensorDesc &in_desc,
784 : GeTensorDesc &format_transfer_input,
785 : GeTensorDesc &format_transfer_output) const {
786 : bool insert_cast_first = InsertCastFirstCheck(out_desc, in_desc);
787 : if (insert_cast_first) {
788 : format_transfer_input = out_desc;
789 : format_transfer_input.SetDataType(in_desc.GetDataType());
790 : format_transfer_output = in_desc;
791 : } else {
792 : format_transfer_input = out_desc;
793 : format_transfer_output = in_desc;
794 : format_transfer_output.SetDataType(out_desc.GetDataType());
795 : }
796 : }
797 :
798 : void TransOpWithoutReshapeFusionPass::GetCastOpDesc(const GeTensorDesc &out_desc, const GeTensorDesc &in_desc,
799 : GeTensorDesc &cast_input, GeTensorDesc &cast_output) const {
800 : bool insert_cast_first = InsertCastFirstCheck(out_desc, in_desc);
801 : if (insert_cast_first) {
802 : cast_input = out_desc;
803 : cast_output = out_desc;
804 : cast_output.SetDataType(in_desc.GetDataType());
805 : } else {
806 : cast_input = in_desc;
807 : cast_input.SetDataType(out_desc.GetDataType());
808 : cast_output = in_desc;
809 : }
810 : }
811 :
812 : void TransOpWithoutReshapeFusionPass::GetBeginOutDescAndEndInDesc(const int32_t index, GeTensorDesc &out_desc,
813 : GeTensorDesc &in_desc) {
814 : auto nodes_anchor = sub_graph_anchors_[index];
815 : auto out_peer_anchor = nodes_anchor.front().second;
816 : GE_CHECK_NOTNULL_JUST_RETURN(out_peer_anchor);
817 : auto out_owner_node = out_peer_anchor->GetOwnerNode();
818 : GE_CHECK_NOTNULL_JUST_RETURN(out_owner_node);
819 : auto out_peer_op_desc = out_owner_node->GetOpDesc();
820 : GE_IF_BOOL_EXEC(
821 : out_peer_op_desc == nullptr, GELOGE(INTERNAL_ERROR, "[Get][OpDesc] failed, out_peer_op_desc is nullptr"); return);
822 : out_desc = out_peer_op_desc->GetInputDesc(out_peer_anchor->GetIdx());
823 :
824 : auto in_peer_anchor = nodes_anchor.back().first;
825 : GE_CHECK_NOTNULL_JUST_RETURN(in_peer_anchor);
826 : auto in_owner_node = in_peer_anchor->GetOwnerNode();
827 : GE_CHECK_NOTNULL_JUST_RETURN(in_owner_node);
828 : auto in_peer_op_desc = in_owner_node->GetOpDesc();
829 : GE_IF_BOOL_EXEC(
830 : in_peer_op_desc == nullptr, GELOGE(INTERNAL_ERROR, "[Get][OpDesc] failed, in_peer_op_desc is nullptr"); return);
831 : in_desc = in_peer_op_desc->GetOutputDesc(in_peer_anchor->GetIdx());
832 : }
833 :
834 : graphStatus TransOpWithoutReshapeFusionPass::FormatFusion(const int32_t index, OpDescPtr &format_transfer_op,
835 : int32_t &fusion_op_count, bool &fusion_continue) {
836 : GeTensorDesc out_desc;
837 : GeTensorDesc in_desc;
838 : GetBeginOutDescAndEndInDesc(index, out_desc, in_desc);
839 :
840 : GeTensorDesc format_transfer_input;
841 : GeTensorDesc format_transfer_output;
842 : GetFormatTransferDesc(out_desc, in_desc, format_transfer_input, format_transfer_output);
843 :
844 : if ((out_desc.GetFormat() == in_desc.GetFormat()) &&
845 : (!ShapeEqualCheck(out_desc.GetShape(), in_desc.GetShape()) ||
846 : !ShapeEqualCheck(out_desc.GetOriginShape(), in_desc.GetOriginShape()))) {
847 : SetRemainNode(sub_graph_anchors_[index]);
848 : return GRAPH_SUCCESS;
849 : }
850 :
851 : if ((out_desc.GetFormat() != in_desc.GetFormat()) && FusionFormatSupport(out_desc.GetFormat()) &&
852 : FusionFormatSupport(in_desc.GetFormat())) {
853 : // create format transop
854 : format_transfer_op = GetFormatTransferOp(format_transfer_input, format_transfer_output);
855 : if (format_transfer_op != nullptr) {
856 : ++fusion_op_count;
857 : GELOGI("support format transfer op %s", format_transfer_op->GetName().c_str());
858 : } else {
859 : GELOGW("ability not support.src format:%d, src datatype:%d, dst format:%d, dst datatype:%d",
860 : format_transfer_input.GetFormat(), format_transfer_input.GetDataType(), format_transfer_output.GetFormat(),
861 : format_transfer_output.GetDataType());
862 : fusion_op_count = kInvalidFusionOpCount;
863 : }
864 : } else if (out_desc.GetFormat() != in_desc.GetFormat()) {
865 : SetRemainNode(sub_graph_anchors_[index]);
866 : return GRAPH_SUCCESS;
867 : }
868 : fusion_continue = true;
869 : return GRAPH_SUCCESS;
870 : }
871 :
872 : graphStatus TransOpWithoutReshapeFusionPass::DataTypeFusion(const int32_t index, OpDescPtr &cast_op,
873 : int32_t &fusion_op_count) {
874 : GeTensorDesc out_desc;
875 : GeTensorDesc in_desc;
876 : GetBeginOutDescAndEndInDesc(index, out_desc, in_desc);
877 :
878 : GeTensorDesc cast_input;
879 : GeTensorDesc cast_output;
880 : GetCastOpDesc(out_desc, in_desc, cast_input, cast_output);
881 :
882 : if ((fusion_op_count != kInvalidFusionOpCount) && (out_desc.GetDataType() != in_desc.GetDataType())) {
883 : // create cast op
884 : cast_op = GetCastOp(cast_input, cast_output);
885 : if (cast_op == nullptr) {
886 : fusion_op_count = kInvalidFusionOpCount;
887 : return GRAPH_FAILED;
888 : }
889 :
890 : bool is_supported = false;
891 : (void)TransOpCreator::CheckAccuracySupported(cast_op, is_supported);
892 : if (is_supported) {
893 : ++fusion_op_count;
894 : GELOGI("support cast op %s. src format:%d, src datatype:%d, dst format:%d, dst datatype:%d",
895 : cast_op->GetName().c_str(), cast_input.GetFormat(), cast_input.GetDataType(), cast_output.GetFormat(),
896 : cast_output.GetDataType());
897 : } else {
898 : GELOGW("ability not support.src format:%d, src datatype:%d, dst format:%d, dst datatype:%d",
899 : cast_input.GetFormat(), cast_input.GetDataType(), cast_output.GetFormat(), cast_output.GetDataType());
900 : fusion_op_count = kInvalidFusionOpCount;
901 : }
902 : }
903 : return GRAPH_SUCCESS;
904 : }
905 :
906 : graphStatus TransOpWithoutReshapeFusionPass::TransOpFuseHandle(const ComputeGraphPtr &graph, const int32_t index) {
907 : bool fusion_continue = false;
908 : OpDescPtr format_transfer_op = nullptr;
909 : int32_t fusion_op_count = 0;
910 : auto fortmat_fusion_ret = FormatFusion(index, format_transfer_op, fusion_op_count, fusion_continue);
911 : if ((fortmat_fusion_ret != GRAPH_SUCCESS) || !fusion_continue) {
912 : SetRemainNode(sub_graph_anchors_[index]);
913 : return GRAPH_SUCCESS;
914 : }
915 :
916 : OpDescPtr cast_op = nullptr;
917 : if (DataTypeFusion(index, cast_op, fusion_op_count) != GRAPH_SUCCESS) {
918 : SetRemainNode(sub_graph_anchors_[index]);
919 : return GRAPH_SUCCESS;
920 : }
921 :
922 : if ((fusion_op_count > 0) && (fusion_op_count < transop_num_count_[index])) {
923 : GeTensorDesc out_desc;
924 : GeTensorDesc in_desc;
925 : GetBeginOutDescAndEndInDesc(index, out_desc, in_desc);
926 : bool insert_cast_first = InsertCastFirstCheck(out_desc, in_desc);
927 : if (InsertNewTransOp(graph, cast_op, format_transfer_op, index, insert_cast_first) != GRAPH_SUCCESS) {
928 : return GRAPH_FAILED;
929 : }
930 : } else {
931 : // remain all nodes
932 : SetRemainNode(sub_graph_anchors_[index]);
933 : }
934 : return GRAPH_SUCCESS;
935 : }
936 :
937 : void TransOpWithoutReshapeFusionPass::RemoveNousedNodes(const ComputeGraphPtr &graph) {
938 : if (graph == nullptr) {
939 : return;
940 : }
941 : for (size_t i = 0; i < sub_graph_nodes_.size(); ++i) {
942 : if (sub_graph_has_reshape_node_[i]) {
943 : continue;
944 : }
945 :
946 : for (const auto &node : sub_graph_nodes_[i]) {
947 : GE_CHECK_NOTNULL_JUST_RETURN(node);
948 : // remove nodes
949 : if (!IsTransOp(node)) {
950 : continue;
951 : }
952 :
953 : auto op_desc = node->GetOpDesc();
954 : GE_CHECK_NOTNULL_JUST_RETURN(op_desc);
955 : bool node_remain_flag = op_desc->TryGetExtAttr(kRemainNode, false);
956 : if (node_remain_flag) {
957 : continue;
958 : }
959 :
960 : GE_IF_BOOL_EXEC(!op_desc->SetExtAttr(kRemainNode, true),
961 : GELOGE(INTERNAL_ERROR, "[Set][ExtAttr] for op:%s failed", op_desc->GetName().c_str());
962 : return);
963 : GELOGI("remove node:%s", node->GetName().c_str());
964 : if (GraphUtils::IsolateNode(node, {0}) != GRAPH_SUCCESS) {
965 : GELOGW("Isolate node: %s failed.", node->GetName().c_str());
966 : continue;
967 : }
968 : if (GraphUtils::RemoveNodeWithoutRelink(graph, node) != GRAPH_SUCCESS) {
969 : GELOGW("Remove node: %s failed.", node->GetName().c_str());
970 : continue;
971 : }
972 : }
973 : }
974 : }
975 :
976 : graphStatus TransOpWithoutReshapeFusionPass::Run(ComputeGraphPtr graph) {
977 : GELOGI("[TransOpWithoutReshapeFusionPass]: optimize begin.");
978 : if (graph == nullptr) {
979 : return GRAPH_SUCCESS;
980 : }
981 :
982 : for (const auto &node : graph->GetDirectNode()) {
983 : GE_CHECK_NOTNULL(node);
984 : if (IsTransOp(node)) {
985 : continue;
986 : }
987 : bool is_unknown = false;
988 : auto ret = NodeUtils::GetNodeUnknownShapeStatus(*node, is_unknown);
989 : if (ret != GRAPH_SUCCESS) {
990 : GELOGW("Get node unknown status failed, node name:%s, type:%s.", node->GetName().c_str(),
991 : node->GetType().c_str());
992 : continue;
993 : }
994 : if (is_unknown) {
995 : GELOGI("Current node %s, type %s is unknown shape which should be skip.", node->GetName().c_str(),
996 : node->GetType().c_str());
997 : continue;
998 : }
999 : GELOGD("Current normal node name: %s, type: %s.", node->GetName().c_str(), node->GetType().c_str());
1000 : for (const auto &out_anchor : node->GetAllOutDataAnchors()) {
1001 : GE_CHECK_NOTNULL(out_anchor);
1002 : std::vector<std::vector<std::pair<OutDataAnchorPtr, InDataAnchorPtr>>> sub_graph_anchors;
1003 : std::vector<std::pair<OutDataAnchorPtr, InDataAnchorPtr>> nodes_list;
1004 : if (GetSubGraphsBetweenNormalNode(out_anchor, sub_graph_anchors, nodes_list) != GRAPH_SUCCESS) {
1005 : GELOGW("get transops failed!");
1006 : continue;
1007 : }
1008 :
1009 : sub_graph_anchors_.swap(sub_graph_anchors);
1010 : EraseInvalidAnchorsPair();
1011 : if (sub_graph_anchors_.empty()) {
1012 : continue;
1013 : }
1014 :
1015 : // check reshape node
1016 : if (GetSubGraphNodesInfo() != GRAPH_SUCCESS) {
1017 : continue;
1018 : }
1019 :
1020 : // save control edge
1021 : GetControlAnchors();
1022 :
1023 : if (TransOpFuse(graph) != GRAPH_SUCCESS) {
1024 : return GRAPH_FAILED;
1025 : }
1026 : }
1027 : }
1028 : GELOGI("[TransOpWithoutReshapeFusionPass]: Optimize end.");
1029 : return GRAPH_SUCCESS;
1030 : }
1031 :
1032 : bool TransOpWithoutReshapeFusionPass::DescEqualCheck(ConstGeTensorDescPtr &desc_src,
1033 : ConstGeTensorDescPtr &desc_dst) const {
1034 : if ((desc_src == nullptr) || (desc_dst == nullptr)) {
1035 : return false;
1036 : }
1037 : if ((desc_src->GetFormat() != desc_dst->GetFormat()) || (desc_src->GetDataType() != desc_dst->GetDataType())) {
1038 : return false;
1039 : }
1040 :
1041 : if (!ShapeEqualCheck(desc_src->GetShape(), desc_dst->GetShape())) {
1042 : return false;
1043 : }
1044 :
1045 : return ShapeEqualCheck(desc_src->GetOriginShape(), desc_dst->GetOriginShape());
1046 : }
1047 :
1048 : bool TransOpWithoutReshapeFusionPass::ShapeEqualCheck(const GeShape &src, const GeShape &dst) const {
1049 : if (src.GetDims().size() != dst.GetDims().size()) {
1050 : return false;
1051 : }
1052 :
1053 : for (size_t i = 0; i < src.GetDims().size(); ++i) {
1054 : if (src.GetDim(i) != dst.GetDim(i)) {
1055 : return false;
1056 : }
1057 : }
1058 : return true;
1059 : }
1060 :
1061 : graphStatus TransOpWithoutReshapeFusionPass::TransOpFuse(const ComputeGraphPtr &graph) {
1062 : for (size_t i = 0; i < sub_graph_anchors_.size(); ++i) {
1063 : if (sub_graph_has_reshape_node_[i]) {
1064 : continue;
1065 : }
1066 :
1067 : auto nodes_anchor = sub_graph_anchors_[i];
1068 : auto out_anchor = nodes_anchor.front().first;
1069 : GE_CHECK_NOTNULL(out_anchor);
1070 : auto out_op_desc = out_anchor->GetOwnerNode()->GetOpDesc();
1071 : GE_CHECK_NOTNULL(out_op_desc);
1072 : auto out_desc = out_op_desc->GetOutputDescPtr(out_anchor->GetIdx());
1073 : GE_CHECK_NOTNULL(out_desc);
1074 : auto in_anchor = nodes_anchor.back().second;
1075 : GE_CHECK_NOTNULL(in_anchor);
1076 : auto in_op_desc = in_anchor->GetOwnerNode()->GetOpDesc();
1077 : GE_CHECK_NOTNULL(in_op_desc);
1078 : auto in_desc = in_op_desc->GetInputDescPtr(in_anchor->GetIdx());
1079 : GE_CHECK_NOTNULL(in_desc);
1080 : if (FusionFormatSupport(out_desc->GetFormat()) && DescEqualCheck(out_desc, in_desc)) {
1081 : // relink begin_out to end_in
1082 : if (RelinkNodesWhenDescNotChanged(nodes_anchor.front(), nodes_anchor.back(), static_cast<int32_t>(i)) !=
1083 : GRAPH_SUCCESS) {
1084 : return GRAPH_FAILED;
1085 : }
1086 : } else {
1087 : if (TransOpFuseHandle(graph, static_cast<int32_t>(i)) != GRAPH_SUCCESS) {
1088 : return GRAPH_FAILED;
1089 : }
1090 : }
1091 : }
1092 : RemoveNousedNodes(graph);
1093 : return GRAPH_SUCCESS;
1094 : }
1095 :
1096 : graphStatus TransOpWithoutReshapeFusionPass::AddTransNode(const ComputeGraphPtr &graph, const OpDescPtr &transop,
1097 : NodePtr &trans_node) const {
1098 : if (graph == nullptr) {
1099 : return GRAPH_SUCCESS;
1100 : }
1101 : if (transop == nullptr) {
1102 : return GRAPH_SUCCESS;
1103 : }
1104 :
1105 : trans_node = graph->AddNode(transop);
1106 : if (trans_node == nullptr) {
1107 : REPORT_INNER_ERR_MSG("E19999", "Add node:%s(%s) to graph:%s failed", transop->GetName().c_str(),
1108 : transop->GetType().c_str(), graph->GetName().c_str());
1109 : GELOGE(GRAPH_FAILED, "[Add][Node] %s(%s) to graph:%s failed", transop->GetName().c_str(),
1110 : transop->GetType().c_str(), graph->GetName().c_str());
1111 : return GRAPH_FAILED;
1112 : }
1113 : return GRAPH_SUCCESS;
1114 : }
1115 :
1116 : graphStatus TransOpWithoutReshapeFusionPass::GetTransNode(const ComputeGraphPtr &graph, const OpDescPtr &cast_op,
1117 : const OpDescPtr &format_transfer_op,
1118 : const bool insert_cast_first,
1119 : std::vector<NodePtr> &new_trans_nodes) const {
1120 : NodePtr format_transfer_node;
1121 : if (AddTransNode(graph, format_transfer_op, format_transfer_node) != GRAPH_SUCCESS) {
1122 : return GRAPH_FAILED;
1123 : }
1124 :
1125 : NodePtr cast_node;
1126 : if (AddTransNode(graph, cast_op, cast_node) != GRAPH_SUCCESS) {
1127 : return GRAPH_FAILED;
1128 : }
1129 :
1130 : if (insert_cast_first) {
1131 : if (cast_node != nullptr) {
1132 : new_trans_nodes.push_back(cast_node);
1133 : }
1134 : if (format_transfer_node != nullptr) {
1135 : new_trans_nodes.push_back(format_transfer_node);
1136 : }
1137 : } else {
1138 : if (format_transfer_node != nullptr) {
1139 : new_trans_nodes.push_back(format_transfer_node);
1140 : }
1141 : if (cast_node != nullptr) {
1142 : new_trans_nodes.push_back(cast_node);
1143 : }
1144 : }
1145 : return GRAPH_SUCCESS;
1146 : }
1147 :
1148 : graphStatus TransOpWithoutReshapeFusionPass::InsertNewTransOp(const ComputeGraphPtr &graph, const OpDescPtr &cast_op,
1149 : const OpDescPtr &format_transfer_op, const int32_t index,
1150 : const bool insert_cast_first) {
1151 : std::vector<NodePtr> new_trans_nodes;
1152 : if (GetTransNode(graph, cast_op, format_transfer_op, insert_cast_first, new_trans_nodes) != GRAPH_SUCCESS) {
1153 : return GRAPH_FAILED;
1154 : }
1155 : if (new_trans_nodes.empty()) {
1156 : GELOGI("No new trans node. Do not need insert new transop.");
1157 : return GRAPH_SUCCESS;
1158 : }
1159 :
1160 : std::pair<OutDataAnchorPtr, InDataAnchorPtr> begin_out = sub_graph_anchors_[index].front();
1161 : std::pair<OutDataAnchorPtr, InDataAnchorPtr> end_in = sub_graph_anchors_[index].back();
1162 : auto out_anchor = begin_out.first;
1163 : GE_CHECK_NOTNULL(out_anchor);
1164 : auto out_owner_node = out_anchor->GetOwnerNode();
1165 : GE_CHECK_NOTNULL(out_owner_node);
1166 : auto in_anchor = end_in.second;
1167 : GE_CHECK_NOTNULL(in_anchor);
1168 : auto in_owner_node = in_anchor->GetOwnerNode();
1169 : GE_CHECK_NOTNULL(in_owner_node);
1170 : GELOGI("remove edge.src:%s, src idx:%d, dst:%s, dst idx:%d", end_in.first->GetOwnerNode()->GetName().c_str(),
1171 : end_in.first->GetIdx(), in_anchor->GetOwnerNode()->GetName().c_str(), in_anchor->GetIdx());
1172 : GE_CHK_STATUS_RET(GraphUtils::RemoveEdge(end_in.first, in_anchor), "[Remove][Edge] between %s and %s failed",
1173 : out_owner_node->GetName().c_str(), in_owner_node->GetName().c_str());
1174 : GELOGI("add edge.src:%s, src idx:%d, dst:%s", out_anchor->GetOwnerNode()->GetName().c_str(), out_anchor->GetIdx(),
1175 : new_trans_nodes.front()->GetName().c_str());
1176 : if (GraphUtils::AddEdge(out_anchor, new_trans_nodes.front()->GetInAnchor(0)) != GRAPH_SUCCESS) {
1177 : REPORT_INNER_ERR_MSG("E19999", "Add edge between op:%s(%s)(index:%d) and op:%s(%s)(index:0) failed",
1178 : out_owner_node->GetName().c_str(), out_owner_node->GetType().c_str(), out_anchor->GetIdx(),
1179 : new_trans_nodes.front()->GetName().c_str(), new_trans_nodes.front()->GetType().c_str());
1180 : GELOGE(GRAPH_FAILED, "[Add][Edge] between op:%s(%s)(index:%d) and op:%s(%s)(index:0) failed",
1181 : out_owner_node->GetName().c_str(), out_owner_node->GetType().c_str(), out_anchor->GetIdx(),
1182 : new_trans_nodes.front()->GetName().c_str(), new_trans_nodes.front()->GetType().c_str());
1183 : return GRAPH_FAILED;
1184 : } else {
1185 : auto old_peer_in_anchor = begin_out.second;
1186 : GE_CHECK_NOTNULL(old_peer_in_anchor);
1187 : UpdateOutputName(out_anchor, old_peer_in_anchor, in_owner_node);
1188 : }
1189 :
1190 : if (new_trans_nodes.size() > 1) {
1191 : GELOGI("add edge.src:%s, dst:%s", new_trans_nodes.front()->GetName().c_str(),
1192 : new_trans_nodes.back()->GetName().c_str());
1193 : if (GraphUtils::AddEdge(new_trans_nodes.front()->GetOutAnchor(0), new_trans_nodes.back()->GetInAnchor(0)) !=
1194 : GRAPH_SUCCESS) {
1195 : REPORT_INNER_ERR_MSG("E19999", "Add edge between op:%s(%s)(index:0) and op:%s(%s)(index:0) failed",
1196 : new_trans_nodes.front()->GetName().c_str(), new_trans_nodes.front()->GetType().c_str(),
1197 : new_trans_nodes.back()->GetName().c_str(), new_trans_nodes.back()->GetType().c_str());
1198 : GELOGE(GRAPH_FAILED, "[Add][Edge] between op:%s(%s)(index:0) and op:%s(%s)(index:0) failed",
1199 : new_trans_nodes.front()->GetName().c_str(), new_trans_nodes.front()->GetType().c_str(),
1200 : new_trans_nodes.back()->GetName().c_str(), new_trans_nodes.back()->GetType().c_str());
1201 : return GRAPH_FAILED;
1202 : } else {
1203 : auto old_peer_out_anchor = end_in.first;
1204 : GE_CHECK_NOTNULL(old_peer_out_anchor);
1205 : UpdateInputName(old_peer_out_anchor, in_anchor, out_owner_node);
1206 : }
1207 : }
1208 : GELOGI("add edge.src:%s, dst:%s, dst idx:%d", new_trans_nodes.back()->GetName().c_str(),
1209 : in_anchor->GetOwnerNode()->GetName().c_str(), in_anchor->GetIdx());
1210 : if (GraphUtils::AddEdge(new_trans_nodes.back()->GetOutAnchor(0), in_anchor) != GRAPH_SUCCESS) {
1211 : REPORT_INNER_ERR_MSG("E19999", "Add edge between op:%s(%s)(index:0) and op:%s(%s)(index:%d) failed",
1212 : new_trans_nodes.front()->GetName().c_str(), new_trans_nodes.front()->GetType().c_str(),
1213 : in_owner_node->GetName().c_str(), in_owner_node->GetType().c_str(), in_anchor->GetIdx());
1214 : GELOGE(GRAPH_FAILED, "[Add][Edge] between op:%s(%s)(index:0) and op:%s(%s)(index:%d) failed",
1215 : new_trans_nodes.front()->GetName().c_str(), new_trans_nodes.front()->GetType().c_str(),
1216 : in_owner_node->GetName().c_str(), in_owner_node->GetType().c_str(), in_anchor->GetIdx());
1217 : return GRAPH_FAILED;
1218 : }
1219 :
1220 : return RelinkControlEdge(index, out_anchor, new_trans_nodes);
1221 : }
1222 :
1223 1 : bool TransOpWithoutReshapeFusionPass::CheckIfHasSameOutControlEdge(const NodePtr node, const NodePtr out_node) const {
1224 : auto out_anchor = node->GetOutControlAnchor();
1225 : for (auto peer_in_anchor : out_anchor->GetPeerInControlAnchors()) {
1226 : if (peer_in_anchor->GetOwnerNode() == out_node) {
1227 : return true;
1228 : }
1229 : }
1230 : return false;
1231 : }
1232 :
1233 : graphStatus TransOpWithoutReshapeFusionPass::AddControlEdgeForNewTransNode(
1234 : const int32_t index, const std::vector<NodePtr> &new_trans_nodes) {
1235 : for (const auto &peer_in_anchor : out_control_peer_in_control_anchors_[index]) {
1236 : GE_CHECK_NOTNULL(peer_in_anchor);
1237 : if (remain_in_control_anchors_.count(peer_in_anchor) > 0) {
1238 : continue;
1239 : }
1240 : GELOGI("add control edge.src:%s, dst:%s", new_trans_nodes.back()->GetName().c_str(),
1241 : peer_in_anchor->GetOwnerNode()->GetName().c_str());
1242 : if (GraphUtils::AddEdge(new_trans_nodes.back()->GetOutControlAnchor(), peer_in_anchor) != GRAPH_SUCCESS) {
1243 : REPORT_INNER_ERR_MSG("E19999", "Add control edge between op:%s(%s) and op:%s(%s) failed",
1244 : new_trans_nodes.back()->GetName().c_str(), new_trans_nodes.back()->GetType().c_str(),
1245 : peer_in_anchor->GetOwnerNode()->GetName().c_str(),
1246 : peer_in_anchor->GetOwnerNode()->GetType().c_str());
1247 : GELOGE(GRAPH_FAILED, "[Add][ControlEdge] between op:%s(%s) and op:%s(%s) failed",
1248 : new_trans_nodes.back()->GetName().c_str(), new_trans_nodes.back()->GetType().c_str(),
1249 : peer_in_anchor->GetOwnerNode()->GetName().c_str(), peer_in_anchor->GetOwnerNode()->GetType().c_str());
1250 : return GRAPH_FAILED;
1251 : }
1252 : }
1253 :
1254 : for (const auto &peer_out_anchor : in_control_peer_out_control_anchors_[index]) {
1255 : GE_CHECK_NOTNULL(peer_out_anchor);
1256 : if (remain_out_control_anchors_.count(peer_out_anchor) > 0) {
1257 : continue;
1258 : }
1259 : if (CheckIfHasSameOutControlEdge(new_trans_nodes.front(), peer_out_anchor->GetOwnerNode())) {
1260 : continue;
1261 : }
1262 : GELOGI("add control edge.src:%s, dst:%s", peer_out_anchor->GetOwnerNode()->GetName().c_str(),
1263 : new_trans_nodes.front()->GetName().c_str());
1264 : if (GraphUtils::AddEdge(peer_out_anchor, new_trans_nodes.front()->GetInControlAnchor()) != GRAPH_SUCCESS) {
1265 : REPORT_INNER_ERR_MSG("E19999", "Add control edge between op:%s(%s) and op:%s(%s) failed",
1266 : peer_out_anchor->GetOwnerNode()->GetName().c_str(),
1267 : peer_out_anchor->GetOwnerNode()->GetType().c_str(),
1268 : new_trans_nodes.front()->GetName().c_str(), new_trans_nodes.front()->GetType().c_str());
1269 : GELOGE(GRAPH_FAILED, "[Add][ControlEdge] between op:%s(%s) and op:%s(%s) failed",
1270 : peer_out_anchor->GetOwnerNode()->GetName().c_str(), peer_out_anchor->GetOwnerNode()->GetType().c_str(),
1271 : new_trans_nodes.front()->GetName().c_str(), new_trans_nodes.front()->GetType().c_str());
1272 : return GRAPH_FAILED;
1273 : }
1274 : }
1275 :
1276 : // deprecated, there is no control anchor link to data anchor
1277 : for (const auto &peer_in_anchor : out_control_peer_in_data_anchors_[index]) {
1278 : GE_CHECK_NOTNULL(peer_in_anchor);
1279 : GELOGI("add control edge.src:%s, dst:%s", new_trans_nodes.back()->GetName().c_str(),
1280 : peer_in_anchor->GetOwnerNode()->GetName().c_str());
1281 : if (GraphUtils::AddEdge(new_trans_nodes.back()->GetOutControlAnchor(), peer_in_anchor) != GRAPH_SUCCESS) {
1282 : REPORT_INNER_ERR_MSG("E19999", "Add control edge between op:%s(%s) and op:%s(%s) failed",
1283 : new_trans_nodes.back()->GetName().c_str(), new_trans_nodes.back()->GetType().c_str(),
1284 : peer_in_anchor->GetOwnerNode()->GetName().c_str(),
1285 : peer_in_anchor->GetOwnerNode()->GetType().c_str());
1286 : GELOGE(GRAPH_FAILED, "[Add][ControlEdge] between op:%s(%s) and op:%s(%s) failed",
1287 : new_trans_nodes.back()->GetName().c_str(), new_trans_nodes.back()->GetType().c_str(),
1288 : peer_in_anchor->GetOwnerNode()->GetName().c_str(), peer_in_anchor->GetOwnerNode()->GetType().c_str());
1289 : return GRAPH_FAILED;
1290 : }
1291 : }
1292 :
1293 : // deprecated, there is no control anchor link to data anchor
1294 : for (const auto &peer_in_anchor : out_data_peer_in_control_anchors_[index]) {
1295 : GE_CHECK_NOTNULL(peer_in_anchor);
1296 : GELOGI("add control edge.src:%s, dst:%s", new_trans_nodes.back()->GetName().c_str(),
1297 : peer_in_anchor->GetOwnerNode()->GetName().c_str());
1298 : if (GraphUtils::AddEdge(new_trans_nodes.back()->GetOutDataAnchor(0), peer_in_anchor) != GRAPH_SUCCESS) {
1299 : REPORT_INNER_ERR_MSG("E19999", "Add edge between op:%s(%s)(index:0) and op:%s(%s)(index:%d) failed",
1300 : new_trans_nodes.back()->GetName().c_str(), new_trans_nodes.back()->GetType().c_str(),
1301 : peer_in_anchor->GetOwnerNode()->GetName().c_str(),
1302 : peer_in_anchor->GetOwnerNode()->GetType().c_str(), peer_in_anchor->GetIdx());
1303 : GELOGE(GRAPH_FAILED, "[Add][Edge] between op:%s(%s)(index:0) and op:%s(%s)(index:%d) failed",
1304 : new_trans_nodes.back()->GetName().c_str(), new_trans_nodes.back()->GetType().c_str(),
1305 : peer_in_anchor->GetOwnerNode()->GetName().c_str(), peer_in_anchor->GetOwnerNode()->GetType().c_str(),
1306 : peer_in_anchor->GetIdx());
1307 : return GRAPH_FAILED;
1308 : }
1309 : }
1310 : return GRAPH_SUCCESS;
1311 : }
1312 :
1313 : graphStatus TransOpWithoutReshapeFusionPass::RelinkControlEdge(const int32_t index, const OutDataAnchorPtr &out_anchor,
1314 : const std::vector<NodePtr> &new_trans_nodes) {
1315 : GE_CHECK_NOTNULL(out_anchor);
1316 : if (sub_graph_has_control_edge_[index]) {
1317 : GELOGI("add control edge.src:%s, dst:%s", out_anchor->GetOwnerNode()->GetName().c_str(),
1318 : new_trans_nodes.front()->GetName().c_str());
1319 : if (GraphUtils::AddEdge(out_anchor->GetOwnerNode()->GetOutControlAnchor(),
1320 : new_trans_nodes.front()->GetInControlAnchor()) != GRAPH_SUCCESS) {
1321 : REPORT_INNER_ERR_MSG("E19999", "Add control edge between op:%s(%s) and op:%s(%s) failed",
1322 : out_anchor->GetOwnerNode()->GetName().c_str(), out_anchor->GetOwnerNode()->GetType().c_str(),
1323 : new_trans_nodes.front()->GetName().c_str(), new_trans_nodes.front()->GetType().c_str());
1324 : GELOGE(GRAPH_FAILED, "[Add][ControlEdge] between op:%s(%s) and op:%s(%s) failed",
1325 : out_anchor->GetOwnerNode()->GetName().c_str(), out_anchor->GetOwnerNode()->GetType().c_str(),
1326 : new_trans_nodes.front()->GetName().c_str(), new_trans_nodes.front()->GetType().c_str());
1327 : return GRAPH_FAILED;
1328 : }
1329 : }
1330 : if (AddControlEdgeForNewTransNode(index, new_trans_nodes) == GRAPH_FAILED) {
1331 : return GRAPH_FAILED;
1332 : }
1333 : if (sub_graph_has_out_data_peer_in_control_edge_[index]) {
1334 : auto in_anchor = sub_graph_anchors_[index].back().second;
1335 : GELOGI("add control edge.src:%s, dst:%s", new_trans_nodes.back()->GetName().c_str(),
1336 : in_anchor->GetOwnerNode()->GetName().c_str());
1337 : if (GraphUtils::AddEdge(new_trans_nodes.back()->GetOutDataAnchor(0),
1338 : in_anchor->GetOwnerNode()->GetInControlAnchor()) != GRAPH_SUCCESS) {
1339 : REPORT_INNER_ERR_MSG("E19999", "Add edge between op:%s(%s) and op:%s(%s) failed",
1340 : new_trans_nodes.back()->GetName().c_str(), new_trans_nodes.back()->GetType().c_str(),
1341 : in_anchor->GetOwnerNode()->GetName().c_str(), in_anchor->GetOwnerNode()->GetType().c_str());
1342 : GELOGE(GRAPH_FAILED, "[Add][Edge] between op:%s(%s) and op:%s(%s) failed",
1343 : new_trans_nodes.back()->GetName().c_str(), new_trans_nodes.back()->GetType().c_str(),
1344 : in_anchor->GetOwnerNode()->GetName().c_str(), in_anchor->GetOwnerNode()->GetType().c_str());
1345 : return GRAPH_FAILED;
1346 : }
1347 : }
1348 : return GRAPH_SUCCESS;
1349 : }
1350 :
1351 : bool TransOpWithoutReshapeFusionPass::FusionFormatSupport(Format format) {
1352 : const auto primary_format = static_cast<Format>(GetPrimaryFormat(static_cast<int32_t>(format)));
1353 : return primary_format == FORMAT_NCHW || primary_format == FORMAT_NHWC || primary_format == FORMAT_FRACTAL_Z ||
1354 : primary_format == FORMAT_NC1HWC0;
1355 : }
1356 :
1357 : graphStatus TransOpWithoutReshapeFusionPass::GetSubGraphsBetweenNormalNode(
1358 : const OutDataAnchorPtr &out_anchor,
1359 : std::vector<std::vector<std::pair<OutDataAnchorPtr, InDataAnchorPtr>>> &sub_graphs_out,
1360 : std::vector<std::pair<OutDataAnchorPtr, InDataAnchorPtr>> &nodes_list) {
1361 : graphStatus ret = GRAPH_SUCCESS;
1362 : if (out_anchor == nullptr) {
1363 : REPORT_INNER_ERR_MSG("E19999", "Param out_anchor is nullptr, check invalid");
1364 : GELOGE(GRAPH_FAILED, "[Check][Param] param out_anchor is nullptr");
1365 : return GRAPH_FAILED;
1366 : }
1367 :
1368 : for (const auto &peer_in_anchor : out_anchor->GetPeerInDataAnchors()) {
1369 : if (peer_in_anchor == nullptr || peer_in_anchor->GetOwnerNode() == nullptr ||
1370 : peer_in_anchor->GetOwnerNode()->GetOpDesc() == nullptr) {
1371 : continue;
1372 : }
1373 :
1374 : nodes_list.emplace_back(out_anchor, peer_in_anchor);
1375 : auto peer_in_node = peer_in_anchor->GetOwnerNode();
1376 : GE_CHECK_NOTNULL(peer_in_node);
1377 : if (!IsTransOp(peer_in_node)) {
1378 : sub_graphs_out.push_back(nodes_list);
1379 : nodes_list.pop_back();
1380 : } else {
1381 : for (const auto &peer_out_anchor : peer_in_node->GetAllOutDataAnchors()) {
1382 : ret = GetSubGraphsBetweenNormalNode(peer_out_anchor, sub_graphs_out, nodes_list);
1383 : if (ret != GRAPH_SUCCESS) {
1384 : GELOGE(GRAPH_FAILED, "[Get][SubGraphs] Between Normal Node failed! node:%s", peer_in_node->GetName().c_str());
1385 : return GRAPH_FAILED;
1386 : }
1387 : }
1388 : nodes_list.pop_back();
1389 : }
1390 : }
1391 : return GRAPH_SUCCESS;
1392 : }
1393 :
1394 : bool TransOpWithoutReshapeFusionPass::IsTransOp(const NodePtr &node) {
1395 : return IsTransOp(node.get());
1396 : }
1397 :
1398 : bool TransOpWithoutReshapeFusionPass::IsTransOp(const Node *node) {
1399 : // The caller guarantees that the pointer is not null.
1400 : return node->GetType() == CAST || node->GetType() == RESHAPE || node->GetType() == TRANSPOSE ||
1401 : node->GetType() == TRANSPOSED || node->GetType() == TRANSDATA;
1402 : }
1403 :
1404 : REG_PASS_OPTION("TransOpWithoutReshapeFusionPass").LEVELS(OoLevel::kO3);
1405 : } // namespace ge
|