You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

flow_ctrl_pass.cc 39 kB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
4 years ago
4 years ago
5 years ago
4 years ago
5 years ago
4 years ago
4 years ago
5 years ago
4 years ago
5 years ago
5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
4 years ago
4 years ago
5 years ago
4 years ago
4 years ago
5 years ago
5 years ago
4 years ago
5 years ago
4 years ago
4 years ago
5 years ago
4 years ago
4 years ago
5 years ago
5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
5 years ago
4 years ago
5 years ago
4 years ago
4 years ago
5 years ago
4 years ago
4 years ago
5 years ago
5 years ago
4 years ago
4 years ago
5 years ago
4 years ago
4 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
4 years ago
4 years ago
5 years ago
4 years ago
5 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
4 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
4 years ago
4 years ago
5 years ago
5 years ago
4 years ago
4 years ago
5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
5 years ago
4 years ago
4 years ago
5 years ago
4 years ago
4 years ago
5 years ago
4 years ago
5 years ago
4 years ago
4 years ago
5 years ago
4 years ago
4 years ago
5 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762
  1. /**
  2. * Copyright 2020 Huawei Technologies Co., Ltd
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include "graph/passes/flow_ctrl_pass.h"
  17. #include <memory>
  18. #include <string>
  19. #include <vector>
  20. #include "framework/common/debug/ge_log.h"
  21. #include "graph/debug/ge_attr_define.h"
  22. #include "common/omg_util.h"
  23. #include "common/ge/ge_util.h"
  24. #include "graph/manager/graph_var_manager.h"
  25. #include "graph/passes/pass_utils.h"
  26. namespace ge {
  27. // when namespace change to ge, please delete the using code.
  28. Status FlowCtrlPass::Run(ComputeGraphPtr compute_graph) {
  29. GE_CHECK_NOTNULL(compute_graph);
  30. if (!PassUtils::IsNeedTrainIteFlowCtrl(compute_graph)) {
  31. GELOGI("No need FlowCtrl for graph %u.", compute_graph->GetGraphID());
  32. return NOT_CHANGED;
  33. }
  34. GELOGI("FlowCtrl pass begin.graph is [%s].", compute_graph->GetName().c_str());
  35. bool graph_change = false;
  36. // 1. Add FP/BP flow ctrl (big cycle)
  37. for (auto &node : compute_graph->GetDirectNode()) {
  38. if (node == nullptr) {
  39. continue;
  40. }
  41. GE_IF_BOOL_EXEC(node->GetOpDesc() == nullptr, continue);
  42. uint32_t true_stream_id = 0;
  43. bool is_found = AttrUtils::GetInt(node->GetOpDesc(), ATTR_NAME_TRUE_BRANCH_STREAM, true_stream_id);
  44. // FP/BP cycle flag is true_stream_id == 0
  45. if (is_found && (true_stream_id == TRUE_STREAM_ID)) {
  46. // Add big cycle
  47. Status ret = AddFpBpIteratorCtrl(compute_graph, node);
  48. if (ret != SUCCESS) {
  49. GELOGE(ret, "[Add][FpBpIteratorCtrl] failed, node:%s, graph:%s.",
  50. node->GetName().c_str(), compute_graph->GetName().c_str());
  51. return ret;
  52. }
  53. graph_change = true;
  54. // only one big cycle, so break.
  55. break;
  56. }
  57. }
  58. // 2. Add special node flow ctrl. eg, IteratorGetNext. (small cycle)
  59. // NOTE: Small cycle share the variables with big cycle.
  60. for (auto &node : compute_graph->GetDirectNode()) {
  61. if (node == nullptr) {
  62. continue;
  63. }
  64. GE_IF_BOOL_EXEC(node->GetOpDesc() == nullptr, continue);
  65. bool need_cycle_flag = false;
  66. (void)AttrUtils::GetBool(node->GetOpDesc(), ATTR_NAME_STREAM_CYCLE_EVENT_FLAG, need_cycle_flag);
  67. // small cycle flag is need_stream_cycle_event == true
  68. if (need_cycle_flag) {
  69. Status ret = AddSpecialNodeIteratorCtrl(compute_graph, node);
  70. if (ret != SUCCESS) {
  71. GELOGE(ret, "[Add][SpecialNodeIteratorCtrl] failed, node:%s, graph:%s.",
  72. node->GetName().c_str(), compute_graph->GetName().c_str());
  73. return ret;
  74. }
  75. graph_change = true;
  76. }
  77. }
  78. // add edge operation below depends on memcpy node in itertor loop set single stream,or may cause block
  79. for (auto &active_node : active_nodes_in_iter_loop_) {
  80. auto ret = GraphUtils::AddEdge(active_node->GetOutControlAnchor(),
  81. assign_add_node_in_fpbp_loop_->GetInControlAnchor());
  82. if (ret != GRAPH_SUCCESS) {
  83. GELOGW("add control edge between iter_loop_node:%s and fpbp_loop_node:%s fail, may cause block",
  84. active_node->GetName().c_str(), assign_add_node_in_fpbp_loop_->GetName().c_str());
  85. }
  86. }
  87. GELOGI("FlowCtrl pass end, graph is %s.", graph_change ? "changed" : "not changed");
  88. return graph_change ? SUCCESS : NOT_CHANGED;
  89. }
  90. bool FlowCtrlPass::CheckMultiDataSet(ComputeGraphPtr &compute_graph) {
  91. int data_set_num = 0;
  92. for (auto &node : compute_graph->GetDirectNode()) {
  93. if (node == nullptr) {
  94. continue;
  95. }
  96. string type;
  97. bool is_found = AttrUtils::GetStr(node->GetOpDesc(), ATTR_NAME_FRAMEWORK_ORIGINAL_TYPE, type);
  98. if (is_found && type == "IteratorV2") {
  99. data_set_num++;
  100. }
  101. }
  102. GELOGI("The ComputeGraph contain %d dataSet.", data_set_num);
  103. return (data_set_num > 1) ? true : false;
  104. }
  105. NodePtr FlowCtrlPass::InsertOp(ComputeGraphPtr &compute_graph, const string &node_type, const string &node_name,
  106. const std::vector<GeTensorDesc> &input_list,
  107. const std::vector<GeTensorDesc> &output_list) {
  108. OpDescPtr op_desc = MakeShared<OpDesc>(node_name, node_type);
  109. if (op_desc == nullptr) {
  110. REPORT_CALL_ERROR("E19999", "New OpDesc failed");
  111. GELOGE(FAILED, "[New][OpDesc] failed, name:%s, type:%s.", node_name.c_str(), node_type.c_str());
  112. return nullptr;
  113. }
  114. for (auto &input_desc : input_list) {
  115. graphStatus graph_status = op_desc->AddInputDesc(input_desc);
  116. if (graph_status != GRAPH_SUCCESS) {
  117. REPORT_CALL_ERROR("E19999", "Add input desc to op:%s(%s) failed",
  118. op_desc->GetName().c_str(), op_desc->GetType().c_str());
  119. GELOGE(FAILED, "[Add][InputDesc] to op:%s(%s) failed", op_desc->GetName().c_str(), op_desc->GetType().c_str());
  120. return nullptr;
  121. }
  122. }
  123. for (auto &output_desc : output_list) {
  124. graphStatus graph_status = op_desc->AddOutputDesc(output_desc);
  125. if (graph_status != GRAPH_SUCCESS) {
  126. REPORT_CALL_ERROR("E19999", "Add output desc to op:%s(%s) failed",
  127. op_desc->GetName().c_str(), op_desc->GetType().c_str());
  128. GELOGE(FAILED, "[Add][OutputDesc] to op:%s(%s) failed",
  129. op_desc->GetName().c_str(), op_desc->GetType().c_str());
  130. return nullptr;
  131. }
  132. }
  133. GE_IF_BOOL_EXEC(compute_graph == nullptr,
  134. REPORT_INNER_ERROR("E19999", "Param compute_graph is nullptr, check invalid");
  135. DOMI_LOGE("[Check][Param] compute_graph is nullptr");
  136. return nullptr);
  137. NodePtr node = compute_graph->AddNode(op_desc);
  138. if (node == nullptr) {
  139. REPORT_CALL_ERROR("E19999", "Add node:%s(%s) to graph:%s failed",
  140. op_desc->GetName().c_str(), op_desc->GetType().c_str(), compute_graph->GetName().c_str());
  141. GELOGE(FAILED, "[Add][Node] %s(%s) to graph:%s failed",
  142. op_desc->GetName().c_str(), op_desc->GetType().c_str(), compute_graph->GetName().c_str());
  143. return nullptr;
  144. }
  145. GELOGI("Insert op success, name:%s, type:%s.", node_name.c_str(), node_type.c_str());
  146. return node;
  147. }
  148. NodePtr FlowCtrlPass::InsertStreamSwitchOp(ComputeGraphPtr &compute_graph, const string &switch_name,
  149. const NodePtr &loop_cond, const NodePtr &iter_per_loop) {
  150. GE_IF_BOOL_EXEC(loop_cond == nullptr || loop_cond->GetOpDesc() == nullptr,
  151. REPORT_INNER_ERROR("E19999", "Param loop_cond or its op_desc is nullptr, check invalid");
  152. GELOGE(FAILED, "[Check][Param] Param loop_cond or its op_desc is nullptr");
  153. return nullptr);
  154. GE_IF_BOOL_EXEC(iter_per_loop == nullptr || iter_per_loop->GetOpDesc() == nullptr,
  155. REPORT_INNER_ERROR("E19999", "Param iter_per_loop or its op_desc is nullptr, check invalid");
  156. GELOGE(FAILED, "[Check][Param] Param iter_per_loop or its op_desc is nullptr");
  157. return nullptr);
  158. std::vector<GeTensorDesc> input_desc_list = {loop_cond->GetOpDesc()->GetOutputDesc(0),
  159. iter_per_loop->GetOpDesc()->GetOutputDesc(0)};
  160. std::vector<GeTensorDesc> output_desc_list;
  161. NodePtr stream_switch = InsertOp(compute_graph, STREAMSWITCH, switch_name, input_desc_list, output_desc_list);
  162. if (stream_switch == nullptr) {
  163. GELOGE(FAILED, "[Insert][StreamSwitchOp] failed, name:%s.", switch_name.c_str());
  164. return nullptr;
  165. }
  166. // set input 0
  167. graphStatus add_ret = GraphUtils::AddEdge(loop_cond->GetOutDataAnchor(0), stream_switch->GetInDataAnchor(0));
  168. if (add_ret != GRAPH_SUCCESS) {
  169. REPORT_CALL_ERROR("E19999", "Add edge between op:%s(%s)(index:0) and op:%s(%s)(index:0) failed",
  170. loop_cond->GetName().c_str(), loop_cond->GetType().c_str(),
  171. stream_switch->GetName().c_str(), stream_switch->GetType().c_str());
  172. GELOGE(FAILED, "[Add][Edge] between op:%s(%s)(index:0) and op:%s(%s)(index:0) failed",
  173. loop_cond->GetName().c_str(), loop_cond->GetType().c_str(),
  174. stream_switch->GetName().c_str(), stream_switch->GetType().c_str());
  175. return nullptr;
  176. }
  177. // set input 1
  178. add_ret = GraphUtils::AddEdge(iter_per_loop->GetOutDataAnchor(0), stream_switch->GetInDataAnchor(1));
  179. if (add_ret != GRAPH_SUCCESS) {
  180. REPORT_CALL_ERROR("E19999", "Add edge between op:%s(%s)(index:0) and op:%s(%s)(index:1) failed",
  181. iter_per_loop->GetName().c_str(), iter_per_loop->GetType().c_str(),
  182. stream_switch->GetName().c_str(), stream_switch->GetType().c_str());
  183. GELOGE(FAILED, "[Add][Edge] between op:%s(%s)(index:0) and op:%s(%s)(index:1) failed",
  184. iter_per_loop->GetName().c_str(), iter_per_loop->GetType().c_str(),
  185. stream_switch->GetName().c_str(), stream_switch->GetType().c_str());
  186. return nullptr;
  187. }
  188. // stream switch op need switch cond by attr.
  189. GE_IF_BOOL_EXEC(!AttrUtils::SetInt(stream_switch->GetOpDesc(), ATTR_NAME_STREAM_SWITCH_COND,
  190. static_cast<int64_t>(RT_LESS)),
  191. REPORT_CALL_ERROR("E19999", "Set Attr:%s to op:%s(%s) failed", ATTR_NAME_STREAM_SWITCH_COND.c_str(),
  192. stream_switch->GetName().c_str(), stream_switch->GetType().c_str());
  193. DOMI_LOGE("[Set][Attr] %s to op:%s(%s) failed", ATTR_NAME_STREAM_SWITCH_COND.c_str(),
  194. stream_switch->GetName().c_str(), stream_switch->GetType().c_str());
  195. return nullptr);
  196. return stream_switch;
  197. }
  198. NodePtr FlowCtrlPass::AddVariableNode(ComputeGraphPtr &compute_graph, const string &name) {
  199. GE_IF_BOOL_EXEC(compute_graph == nullptr,
  200. REPORT_INNER_ERROR("E19999", "Param compute_graph is nullptr, check invalid");
  201. DOMI_LOGE("[Check][Param] compute_graph is nullptr");
  202. return nullptr);
  203. NodePtr exist_node = compute_graph->FindNode(name);
  204. if (exist_node != nullptr) {
  205. GELOGD("Node %s already exist, no need add.", name.c_str());
  206. return exist_node;
  207. }
  208. // fetch and set tensor desc
  209. GeTensorDesc tensor_desc;
  210. if (ge::VarManager::Instance(compute_graph->GetSessionID()) == nullptr) {
  211. REPORT_INNER_ERROR("E19999", "Get VarManager by session_id:%lu failed", compute_graph->GetSessionID());
  212. return nullptr;
  213. }
  214. Status ret = ge::VarManager::Instance(compute_graph->GetSessionID())->GetCurVarDesc(name, tensor_desc);
  215. if (ret != SUCCESS) {
  216. REPORT_INNER_ERROR("E19999", "Get var tensor from VarManager by name:%s failed, session_id:%lu",
  217. name.c_str(), compute_graph->GetSessionID());
  218. GELOGE(FAILED, "[Get][CurVarDesc] failed, name:%s, session_id:%lu", name.c_str(), compute_graph->GetSessionID());
  219. return nullptr;
  220. }
  221. std::vector<GeTensorDesc> input_desc_list;
  222. std::vector<GeTensorDesc> output_desc_list = {tensor_desc};
  223. // insert node
  224. return InsertOp(compute_graph, VARIABLE, name, input_desc_list, output_desc_list);
  225. }
  226. Status FlowCtrlPass::AddGlobalStepVariableNode(ComputeGraphPtr &compute_graph) {
  227. NodePtr output_node = compute_graph->FindFirstNodeMatchType(NETOUTPUT);
  228. if (output_node == nullptr) {
  229. GELOGD("Node type %s can't be found in graph %u", NETOUTPUT, compute_graph->GetGraphID());
  230. return SUCCESS;
  231. }
  232. // Global step just add to main graph's netoutput node.And the main graph must be known shape
  233. if ((compute_graph->GetParentGraph() != nullptr) ||
  234. ((compute_graph->GetParentGraph() == nullptr) && (GraphUtils::IsUnknownShapeGraph(compute_graph)))) {
  235. GELOGD("Subgraph %s no need global step variable.", compute_graph->GetName().c_str());
  236. return SUCCESS;
  237. }
  238. NodePtr exist_node = compute_graph->FindNode(NODE_NAME_GLOBAL_STEP);
  239. if (exist_node != nullptr) {
  240. GELOGD("Node %s already exist, no need add.", NODE_NAME_GLOBAL_STEP.c_str());
  241. return SUCCESS;
  242. }
  243. // set global step tensor desc
  244. GeTensorDesc tensor_desc(GeShape({1}), FORMAT_ND, DT_UINT64);
  245. std::vector<GeTensorDesc> input_desc_list = {};
  246. std::vector<GeTensorDesc> output_desc_list = {tensor_desc};
  247. NodePtr global_step = InsertOp(compute_graph, VARIABLE, NODE_NAME_GLOBAL_STEP,
  248. input_desc_list, output_desc_list);
  249. if (global_step == nullptr) {
  250. GELOGE(FAILED, "[Insert][Op] in graph:%s failed, global_step is null.", compute_graph->GetName().c_str());
  251. return FAILED;
  252. }
  253. // add ctrl edges
  254. graphStatus add_ret = GraphUtils::AddEdge(global_step->GetOutControlAnchor(), output_node->GetInControlAnchor());
  255. if (add_ret != GRAPH_SUCCESS) {
  256. REPORT_CALL_ERROR("E19999", "Add control edge between op:%s(%s) and op:%s(%s) failed",
  257. global_step->GetName().c_str(), global_step->GetType().c_str(),
  258. output_node->GetName().c_str(), output_node->GetType().c_str());
  259. GELOGE(FAILED, "[Add][ControlEdge] between op:%s(%s) and op:%s(%s) failed",
  260. global_step->GetName().c_str(), global_step->GetType().c_str(),
  261. output_node->GetName().c_str(), output_node->GetType().c_str());
  262. return FAILED;
  263. }
  264. GELOGD("Add global_step to netoutput edge in graph %u success", compute_graph->GetGraphID());
  265. return SUCCESS;
  266. }
  267. NodePtr FlowCtrlPass::InsertAssignOp(ge::ComputeGraphPtr &compute_graph, const string &node_type,
  268. const string &node_name, const NodePtr &ref_node, const NodePtr &value_node) {
  269. GE_IF_BOOL_EXEC(ref_node == nullptr || value_node == nullptr ||
  270. ref_node->GetOpDesc() == nullptr || value_node->GetOpDesc() == nullptr,
  271. REPORT_INNER_ERROR("E19999", "Param ref_node or value_node or their op_desc is nullptr, "
  272. "check invalid");
  273. GELOGE(FAILED, "[Check][Param] Param ref_node or value_node or their op_desc is nullptr");
  274. return nullptr);
  275. GeTensorDesc ref_tensor_desc = ref_node->GetOpDesc()->GetOutputDesc(0);
  276. GeTensorDesc val_tensor_desc = value_node->GetOpDesc()->GetOutputDesc(0);
  277. std::vector<GeTensorDesc> input_desc_list = {ref_tensor_desc, val_tensor_desc};
  278. std::vector<GeTensorDesc> output_desc_list = {ref_tensor_desc};
  279. NodePtr assign_node = InsertOp(compute_graph, node_type, node_name, input_desc_list, output_desc_list);
  280. if (assign_node == nullptr) {
  281. GELOGE(FAILED, "[Insert][node] %s(%s) failed.", node_name.c_str(), node_type.c_str());
  282. return nullptr;
  283. }
  284. // assign node input 0 = ref_node
  285. graphStatus add_ret = GraphUtils::AddEdge(ref_node->GetOutDataAnchor(0), assign_node->GetInDataAnchor(0));
  286. if (add_ret != GRAPH_SUCCESS) {
  287. REPORT_CALL_ERROR("E19999", "Add edge between op:%s(%s)(index:0) and op:%s(%s)(index:0) failed",
  288. ref_node->GetName().c_str(), ref_node->GetType().c_str(),
  289. assign_node->GetName().c_str(), assign_node->GetType().c_str());
  290. GELOGE(FAILED, "[Add][Edge] between op:%s(%s)(index:0) and op:%s(%s)(index:0) failed",
  291. ref_node->GetName().c_str(), ref_node->GetType().c_str(),
  292. assign_node->GetName().c_str(), assign_node->GetType().c_str());
  293. return nullptr;
  294. }
  295. // assign input 1 = value_node
  296. add_ret = GraphUtils::AddEdge(value_node->GetOutDataAnchor(0), assign_node->GetInDataAnchor(1));
  297. if (add_ret != GRAPH_SUCCESS) {
  298. REPORT_CALL_ERROR("E19999", "Add edge between op:%s(%s)(index:0) and op:%s(%s)(index:1) failed",
  299. value_node->GetName().c_str(), value_node->GetType().c_str(),
  300. assign_node->GetName().c_str(), assign_node->GetType().c_str());
  301. GELOGE(FAILED, "[Add][Edge] between op:%s(%s)(index:0) and op:%s(%s)(index:1) failed",
  302. value_node->GetName().c_str(), value_node->GetType().c_str(),
  303. assign_node->GetName().c_str(), assign_node->GetType().c_str());
  304. return nullptr;
  305. }
  306. (void)ge::AttrUtils::SetBool(assign_node->GetOpDesc(), ATTR_NEED_COMPILE, true);
  307. return assign_node;
  308. }
  309. Status FlowCtrlPass::CreateIterCtrlTrueBranch(ComputeGraphPtr &compute_graph, const NodePtr &loop_cond_node,
  310. const NodePtr &loop_inc_node, NodePtr &switch_node) {
  311. /*
  312. * loopCond
  313. * |
  314. * v
  315. * switch --> AssignAdd --> active
  316. * ^
  317. * |
  318. * loopIncrement
  319. */
  320. // Insert AssignAdd node
  321. assign_add_node_in_fpbp_loop_ =
  322. InsertAssignOp(compute_graph, ASSIGNADD, NODE_NAME_FLOWCTRL_LOOP_ASSIGNADD, loop_cond_node, loop_inc_node);
  323. if (assign_add_node_in_fpbp_loop_ == nullptr || switch_node == nullptr) {
  324. GELOGE(PARAM_INVALID, "[Check][Param] assign add node or switch node is null");
  325. return FAILED;
  326. }
  327. string active_name = switch_node->GetName() + "_StreamActive";
  328. // add attr for stream assign model to break branch.
  329. auto status = SetStreamLabel(assign_add_node_in_fpbp_loop_, active_name);
  330. if (status != ge::SUCCESS) {
  331. REPORT_CALL_ERROR("E19999", "Set stream_label:%s to op:%s(%s) failed",
  332. active_name.c_str(), assign_add_node_in_fpbp_loop_->GetName().c_str(),
  333. assign_add_node_in_fpbp_loop_->GetType().c_str());
  334. GELOGE(status, "[Set][StreamLabel] %s to op:%s(%s) failed",
  335. active_name.c_str(), assign_add_node_in_fpbp_loop_->GetName().c_str(),
  336. assign_add_node_in_fpbp_loop_->GetType().c_str());
  337. return status;
  338. }
  339. // used for stream assign to find true branch
  340. status = SetActiveLabelList(switch_node, { active_name });
  341. if (status != ge::SUCCESS) {
  342. REPORT_CALL_ERROR("E19999", "Set active label list:%s to op:%s(%s) failed",
  343. active_name.c_str(), switch_node->GetName().c_str(), switch_node->GetType().c_str());
  344. GELOGE(status, "[Set][ActiveLabelList] %s to op:%s(%s) failed",
  345. active_name.c_str(), switch_node->GetName().c_str(), switch_node->GetType().c_str());
  346. return status;
  347. }
  348. // 2. Insert active node
  349. NodePtr active_node = InsertOp(compute_graph, STREAMACTIVE, active_name, {}, {});
  350. if (active_node == nullptr) {
  351. GELOGE(FAILED, "[Insert][StreamActiveNode] %s for IterCtrlTrueStream failed.", active_name.c_str());
  352. return FAILED;
  353. }
  354. status = SetStreamLabel(active_node, active_name);
  355. if (status != ge::SUCCESS) {
  356. REPORT_CALL_ERROR("E19999", "Set stream_label:%s to op:%s(%s) failed",
  357. active_name.c_str(), active_node->GetName().c_str(), active_node->GetType().c_str());
  358. GELOGE(status, "[Set][StreamLabel] %s to op:%s(%s) failed",
  359. active_name.c_str(), active_node->GetName().c_str(), active_node->GetType().c_str());
  360. return status;
  361. }
  362. GE_IF_BOOL_EXEC(!AttrUtils::SetBool(active_node->GetOpDesc(), ATTR_NAME_IS_LOOP_ACTIVE, true),
  363. REPORT_CALL_ERROR("E19999", "Set Attr:%s to op:%s(%s) failed",
  364. ATTR_NAME_IS_LOOP_ACTIVE.c_str(),
  365. active_node->GetName().c_str(), active_node->GetType().c_str());
  366. DOMI_LOGE("[Set][Attr] %s to op:%s(%s) failed", ATTR_NAME_IS_LOOP_ACTIVE.c_str(),
  367. active_node->GetName().c_str(), active_node->GetType().c_str());
  368. return FAILED);
  369. // add ctrl edges
  370. graphStatus add_ret = GraphUtils::AddEdge(switch_node->GetOutControlAnchor(),
  371. assign_add_node_in_fpbp_loop_->GetInControlAnchor());
  372. if (add_ret != GRAPH_SUCCESS) {
  373. REPORT_CALL_ERROR("E19999", "Add control edge between op:%s(%s) and op:%s(%s) failed",
  374. switch_node->GetName().c_str(), switch_node->GetType().c_str(),
  375. assign_add_node_in_fpbp_loop_->GetName().c_str(),
  376. assign_add_node_in_fpbp_loop_->GetType().c_str());
  377. GELOGE(FAILED, "[Add][ControlEdge] between op:%s(%s) and op:%s(%s) failed",
  378. switch_node->GetName().c_str(), switch_node->GetType().c_str(),
  379. assign_add_node_in_fpbp_loop_->GetName().c_str(), assign_add_node_in_fpbp_loop_->GetType().c_str());
  380. return FAILED;
  381. }
  382. add_ret = GraphUtils::AddEdge(assign_add_node_in_fpbp_loop_->GetOutControlAnchor(),
  383. active_node->GetInControlAnchor());
  384. if (add_ret != GRAPH_SUCCESS) {
  385. REPORT_CALL_ERROR("E19999", "Add control edge between op:%s(%s) and op:%s(%s) failed",
  386. assign_add_node_in_fpbp_loop_->GetName().c_str(),
  387. assign_add_node_in_fpbp_loop_->GetType().c_str(),
  388. active_node->GetName().c_str(), active_node->GetType().c_str());
  389. GELOGE(FAILED, "[Add][ControlEdge] between op:%s(%s) and op:%s(%s) failed",
  390. assign_add_node_in_fpbp_loop_->GetName().c_str(), assign_add_node_in_fpbp_loop_->GetType().c_str(),
  391. active_node->GetName().c_str(), active_node->GetType().c_str());
  392. return FAILED;
  393. }
  394. GELOGI("CreateIterCtrlTrueBranch success. StreamActive op:%s.", active_node->GetName().c_str());
  395. return SUCCESS;
  396. }
  397. Status FlowCtrlPass::CreateIterCtrlFalseBranch(ComputeGraphPtr &compute_graph, const NodePtr &loop_cond_node,
  398. const NodePtr &loop_reset_node, NodePtr &switch_node) {
  399. /*
  400. * loopCond
  401. * |
  402. * v
  403. * switch --> Assign --> active --> ModelExit
  404. * ^
  405. * |
  406. * loopReset
  407. */
  408. // Insert Assign node and ctrl edge
  409. NodePtr assign_node =
  410. InsertAssignOp(compute_graph, ASSIGN, NODE_NAME_FLOWCTRL_LOOP_ASSIGN, loop_cond_node, loop_reset_node);
  411. if (assign_node == nullptr || switch_node == nullptr) {
  412. GELOGE(PARAM_INVALID, "[Check][Param] assign_node or switch node is null.");
  413. return FAILED;
  414. }
  415. auto status = SetStreamLabel(assign_node, switch_node->GetName());
  416. if (status != ge::SUCCESS) {
  417. REPORT_CALL_ERROR("E19999", "Set stream_label:%s to op:%s(%s) failed",
  418. switch_node->GetName().c_str(), assign_node->GetName().c_str(), assign_node->GetType().c_str());
  419. GELOGE(status, "[Set][StreamLabel] %s to op:%s(%s) failed",
  420. switch_node->GetName().c_str(), assign_node->GetName().c_str(), assign_node->GetType().c_str());
  421. return status;
  422. }
  423. graphStatus add_ret = GraphUtils::AddEdge(switch_node->GetOutControlAnchor(), assign_node->GetInControlAnchor());
  424. if (add_ret != GRAPH_SUCCESS) {
  425. REPORT_CALL_ERROR("E19999", "Add control edge between op:%s(%s) and op:%s(%s) failed",
  426. switch_node->GetName().c_str(), switch_node->GetType().c_str(),
  427. assign_node->GetName().c_str(), assign_node->GetType().c_str());
  428. GELOGE(FAILED, "[Add][ControlEdge] between op:%s(%s) and op:%s(%s) failed",
  429. switch_node->GetName().c_str(), switch_node->GetType().c_str(),
  430. assign_node->GetName().c_str(), assign_node->GetType().c_str());
  431. return FAILED;
  432. }
  433. if (CheckMultiDataSet(compute_graph)) {
  434. GELOGI("Multi dataSae exist, model_exit node is need.");
  435. // 2. Insert active node and add ctrl edge
  436. string active_name = switch_node->GetName() + "_StreamExitActive";
  437. NodePtr active_node = InsertOp(compute_graph, STREAMACTIVE, active_name, {}, {});
  438. if (active_node == nullptr) {
  439. GELOGE(FAILED, "[Insert][StreamActiveNode] %s for IterCtrlTrueStream failed.", active_name.c_str());
  440. return FAILED;
  441. }
  442. status = SetStreamLabel(active_node, switch_node->GetName());
  443. if (status != ge::SUCCESS) {
  444. REPORT_CALL_ERROR("E19999", "Set stream_label:%s to op:%s(%s) failed", switch_node->GetName().c_str(),
  445. active_node->GetName().c_str(), active_node->GetType().c_str());
  446. GELOGE(status, "[Set][StreamLabel] %s to op:%s(%s) failed", switch_node->GetName().c_str(),
  447. active_node->GetName().c_str(), active_node->GetType().c_str());
  448. return status;
  449. }
  450. GE_CHK_STATUS_RET(SetSwitchBranchNodeLabel(active_node, switch_node->GetName()),
  451. "[Set][SwitchBranchNodeLabel] %s to op:%s(%s) failed", switch_node->GetName().c_str(),
  452. active_node->GetName().c_str(), active_node->GetType().c_str());
  453. string model_exit_name = switch_node->GetName() + "_ModelExit";
  454. status = SetActiveLabelList(active_node, { model_exit_name });
  455. if (status != ge::SUCCESS) {
  456. REPORT_CALL_ERROR("E19999", "Set active label list:%s to op:%s(%s) failed",
  457. model_exit_name.c_str(), active_node->GetName().c_str(), active_node->GetType().c_str());
  458. GELOGE(status, "[Set][ActiveLabelList] %s to op:%s(%s) failed",
  459. model_exit_name.c_str(), active_node->GetName().c_str(), active_node->GetType().c_str());
  460. return status;
  461. }
  462. add_ret = GraphUtils::AddEdge(assign_node->GetOutControlAnchor(), active_node->GetInControlAnchor());
  463. if (add_ret != GRAPH_SUCCESS) {
  464. REPORT_CALL_ERROR("E19999", "Add control edge between op:%s(%s) and op:%s(%s) failed",
  465. assign_node->GetName().c_str(), assign_node->GetType().c_str(),
  466. active_node->GetName().c_str(), active_node->GetType().c_str());
  467. GELOGE(FAILED, "[Add][ControlEdge] between op:%s(%s) and op:%s(%s) failed",
  468. assign_node->GetName().c_str(), assign_node->GetType().c_str(),
  469. active_node->GetName().c_str(), active_node->GetType().c_str());
  470. return FAILED;
  471. }
  472. // 3. Insert model exit node and add ctrl edge
  473. NodePtr model_exit_node = InsertOp(compute_graph, MODELEXIT, model_exit_name, {}, {});
  474. if (model_exit_node == nullptr) {
  475. GELOGE(FAILED, "[Insert][ModelExitNode] %s for IterCtrlTrueStream failed.", model_exit_name.c_str());
  476. return FAILED;
  477. }
  478. status = SetStreamLabel(model_exit_node, model_exit_name);
  479. if (status != ge::SUCCESS) {
  480. REPORT_CALL_ERROR("E19999", "Set stream_label:%s to op:%s(%s) failed",
  481. model_exit_name.c_str(), model_exit_node->GetName().c_str(),
  482. model_exit_node->GetType().c_str());
  483. GELOGE(status, "[Set][StreamLabel] %s to op:%s(%s) failed", model_exit_name.c_str(),
  484. model_exit_node->GetName().c_str(), model_exit_node->GetType().c_str());
  485. return status;
  486. }
  487. add_ret = GraphUtils::AddEdge(active_node->GetOutControlAnchor(), model_exit_node->GetInControlAnchor());
  488. if (add_ret != GRAPH_SUCCESS) {
  489. REPORT_CALL_ERROR("E19999", "Add control edge between op:%s(%s) and op:%s(%s) failed",
  490. active_node->GetName().c_str(), assign_node->GetType().c_str(),
  491. model_exit_node->GetName().c_str(), model_exit_node->GetType().c_str());
  492. GELOGE(FAILED, "[Add][ControlEdge] between op:%s(%s) and op:%s(%s) failed",
  493. active_node->GetName().c_str(), assign_node->GetType().c_str(),
  494. model_exit_node->GetName().c_str(), model_exit_node->GetType().c_str());
  495. return FAILED;
  496. }
  497. }
  498. GELOGI("CreateIterCtrlFalseBranch success.");
  499. return SUCCESS;
  500. }
  501. Status FlowCtrlPass::AddFpBpIteratorCtrl(ComputeGraphPtr &compute_graph, NodePtr &pre_node) {
  502. GE_IF_BOOL_EXEC(pre_node == nullptr, DOMI_LOGE("[Check][Param] pre_node is nullptr."); return FAILED);
  503. string pre_node_name = pre_node->GetName();
  504. GELOGI("Add FpBp Iterator ctrl, pre node:%s.", pre_node_name.c_str());
  505. // 1. Get or add variables
  506. NodePtr loop_cond_node = AddVariableNode(compute_graph, NODE_NAME_FLOWCTRL_LOOP_COND);
  507. if (loop_cond_node == nullptr) {
  508. GELOGE(FAILED, "[Add][Variable] %s failed.", NODE_NAME_FLOWCTRL_LOOP_COND.c_str());
  509. return FAILED;
  510. }
  511. NodePtr loop_inc_node = AddVariableNode(compute_graph, NODE_NAME_FLOWCTRL_LOOP_INCREMENT);
  512. if (loop_inc_node == nullptr) {
  513. GELOGE(FAILED, "[Add][Variable] %s failed.", NODE_NAME_FLOWCTRL_LOOP_INCREMENT.c_str());
  514. return FAILED;
  515. }
  516. NodePtr loop_reset_node = AddVariableNode(compute_graph, NODE_NAME_FLOWCTRL_LOOP_RESETVALUE);
  517. if (loop_reset_node == nullptr) {
  518. GELOGE(FAILED, "[Add][Variable] %s failed.", NODE_NAME_FLOWCTRL_LOOP_RESETVALUE.c_str());
  519. return FAILED;
  520. }
  521. NodePtr iter_per_loop_node = AddVariableNode(compute_graph, NODE_NAME_FLOWCTRL_LOOP_PER_ITER);
  522. if (iter_per_loop_node == nullptr) {
  523. GELOGE(FAILED, "[Add][Variable] %s failed.", NODE_NAME_FLOWCTRL_LOOP_PER_ITER.c_str());
  524. return FAILED;
  525. }
  526. // 2. Add StreamSwitch
  527. string switch_name = pre_node_name + "_" + NODE_NAME_STREAM_SWITCH;
  528. NodePtr switch_node = InsertStreamSwitchOp(compute_graph, switch_name, loop_cond_node, iter_per_loop_node);
  529. if (switch_node == nullptr) {
  530. GELOGE(FAILED, "[Insert][StreamSwitchOp] %s failed.", switch_name.c_str());
  531. return FAILED;
  532. }
  533. auto status = SetStreamLabel(switch_node, switch_name);
  534. if (status != ge::SUCCESS) {
  535. REPORT_CALL_ERROR("E19999", "Set stream label:%s to op:%s(%s) failed",
  536. switch_name.c_str(), switch_node->GetName().c_str(), switch_node->GetType().c_str());
  537. GELOGE(status, "[Set][StreamLabel] %s to op:%s(%s) failed",
  538. switch_name.c_str(), switch_node->GetName().c_str(), switch_node->GetType().c_str());
  539. return status;
  540. }
  541. graphStatus add_ret = GraphUtils::AddEdge(pre_node->GetOutControlAnchor(), switch_node->GetInControlAnchor());
  542. if (add_ret != GRAPH_SUCCESS) {
  543. REPORT_CALL_ERROR("E19999", "Add control edge between op:%s(%s) and op:%s(%s) failed",
  544. pre_node->GetName().c_str(), pre_node->GetType().c_str(),
  545. switch_node->GetName().c_str(), switch_node->GetType().c_str());
  546. GELOGE(FAILED, "[Add][ControlEdge] between op:%s(%s) and op:%s(%s) failed",
  547. pre_node->GetName().c_str(), pre_node->GetType().c_str(),
  548. switch_node->GetName().c_str(), switch_node->GetType().c_str());
  549. return FAILED;
  550. }
  551. // 3. Create switch false branch: return results and reset the loopCond
  552. Status ret = CreateIterCtrlFalseBranch(compute_graph, loop_cond_node, loop_reset_node, switch_node);
  553. if (ret != SUCCESS) {
  554. GELOGE(ret, "[Create][IterCtrlFalseBranch] fail, pre node:%s.", pre_node_name.c_str());
  555. return ret;
  556. }
  557. // 4. Create switch true branch:
  558. // active train streams and increase the loopCond
  559. ret = CreateIterCtrlTrueBranch(compute_graph, loop_cond_node, loop_inc_node, switch_node);
  560. if (ret != SUCCESS) {
  561. GELOGE(ret, "[Create][IterCtrlTrueBranch] fail, pre node:%s.", pre_node_name.c_str());
  562. return ret;
  563. }
  564. return SUCCESS;
  565. }
  566. Status FlowCtrlPass::AddSpecialNodeIteratorCtrl(ComputeGraphPtr &compute_graph, NodePtr &loop_after_node) {
  567. /*
  568. * before add:
  569. * iterator
  570. * |
  571. * v
  572. * MemcpyAsync
  573. *
  574. * after add:
  575. * iterator ----------┐
  576. * | ┆c
  577. * v c v c
  578. * MemcpyAsync-----> switch -----> active
  579. * ^
  580. * / \
  581. * itersPerLoop loopCond
  582. */
  583. GE_IF_BOOL_EXEC(loop_after_node == nullptr || compute_graph == nullptr,
  584. REPORT_INNER_ERROR("E19999", "Param loop_after_node or compute_graph is nullptr, check invalid");
  585. DOMI_LOGE("[Check][Param] loop after node or compute graph is null.");
  586. return FAILED);
  587. InDataAnchorPtr in_anchor = loop_after_node->GetInDataAnchor(0);
  588. if (in_anchor == nullptr || in_anchor->GetPeerOutAnchor() == nullptr) {
  589. REPORT_INNER_ERROR("E19999", "Param loop_after_node:%s(%s) no in data node, check invalid",
  590. loop_after_node->GetName().c_str(), loop_after_node->GetType().c_str());
  591. GELOGE(FAILED, "[Check][Param] Param loop_after_node:%s(%s) no in data node.",
  592. loop_after_node->GetName().c_str(), loop_after_node->GetType().c_str());
  593. return FAILED;
  594. }
  595. NodePtr loop_pre_node = in_anchor->GetPeerOutAnchor()->GetOwnerNode();
  596. // 1. Get variables
  597. NodePtr loop_cond_node = compute_graph->FindNode(NODE_NAME_FLOWCTRL_LOOP_COND);
  598. if (loop_cond_node == nullptr) {
  599. REPORT_INNER_ERROR("E19999", "Node:%s not found in graph:%s, check invalid",
  600. NODE_NAME_FLOWCTRL_LOOP_COND.c_str(), compute_graph->GetName().c_str());
  601. GELOGE(FAILED, "[Check][Param] Node:%s not found in graph:%s.",
  602. NODE_NAME_FLOWCTRL_LOOP_COND.c_str(), compute_graph->GetName().c_str());
  603. return FAILED;
  604. }
  605. NodePtr iter_per_loop_node = compute_graph->FindNode(NODE_NAME_FLOWCTRL_LOOP_PER_ITER);
  606. if (iter_per_loop_node == nullptr) {
  607. REPORT_INNER_ERROR("E19999", "Node:%s not found in graph:%s, check invalid",
  608. NODE_NAME_FLOWCTRL_LOOP_PER_ITER.c_str(), compute_graph->GetName().c_str());
  609. GELOGE(FAILED, "[Check][Param] Node:%s not found in graph:%s.",
  610. NODE_NAME_FLOWCTRL_LOOP_PER_ITER.c_str(), compute_graph->GetName().c_str());
  611. return FAILED;
  612. }
  613. // 2. Add StreamSwitch and edges to switch_node.
  614. GE_IF_BOOL_EXEC(loop_pre_node == nullptr,
  615. REPORT_INNER_ERROR("E19999", "Param loop_after_node:%s(%s) no in data node, check invalid",
  616. loop_after_node->GetName().c_str(), loop_after_node->GetType().c_str());
  617. DOMI_LOGE("[Check][Param] Param loop_after_node:%s(%s) no in data node",
  618. loop_after_node->GetName().c_str(), loop_after_node->GetType().c_str());
  619. return FAILED);
  620. string switch_name = loop_pre_node->GetName() + "_" + NODE_NAME_STREAM_SWITCH;
  621. NodePtr switch_node = InsertStreamSwitchOp(compute_graph, switch_name, loop_cond_node, iter_per_loop_node);
  622. if (switch_node == nullptr) {
  623. GELOGE(FAILED, "[Insert][StreamSwitchOp] %s failed.", switch_name.c_str());
  624. return FAILED;
  625. }
  626. auto status = SetStreamLabel(switch_node, switch_name);
  627. if (status != ge::SUCCESS) {
  628. REPORT_CALL_ERROR("E19999", "Set stream label:%s to op:%s(%s) failed",
  629. switch_name.c_str(), switch_node->GetName().c_str(), switch_node->GetType().c_str());
  630. GELOGE(status, "[Set][StreamLabel] %s to op:%s(%s) failed",
  631. switch_name.c_str(), switch_node->GetName().c_str(), switch_node->GetType().c_str());
  632. return status;
  633. }
  634. graphStatus add_ret = GraphUtils::AddEdge(loop_pre_node->GetOutControlAnchor(), switch_node->GetInControlAnchor());
  635. if (add_ret != GRAPH_SUCCESS) {
  636. REPORT_CALL_ERROR("E19999", "Add control edge between op:%s(%s) and op:%s(%s) failed",
  637. loop_pre_node->GetName().c_str(), loop_pre_node->GetType().c_str(),
  638. switch_node->GetName().c_str(), switch_node->GetType().c_str());
  639. GELOGE(FAILED, "[Add][ControlEdge] between op:%s(%s) and op:%s(%s) failed",
  640. loop_pre_node->GetName().c_str(), loop_pre_node->GetType().c_str(),
  641. switch_node->GetName().c_str(), switch_node->GetType().c_str());
  642. return FAILED;
  643. }
  644. add_ret = GraphUtils::AddEdge(loop_after_node->GetOutControlAnchor(), switch_node->GetInControlAnchor());
  645. if (add_ret != GRAPH_SUCCESS) {
  646. REPORT_CALL_ERROR("E19999", "Add control edge between op:%s(%s) and op:%s(%s) failed",
  647. loop_after_node->GetName().c_str(), loop_after_node->GetType().c_str(),
  648. switch_node->GetName().c_str(), switch_node->GetType().c_str());
  649. GELOGE(FAILED, "[Add][ControlEdge] between op:%s(%s) and op:%s(%s) failed",
  650. loop_after_node->GetName().c_str(), loop_after_node->GetType().c_str(),
  651. switch_node->GetName().c_str(), switch_node->GetType().c_str());
  652. return FAILED;
  653. }
  654. // 3. Create switch true branch: only active
  655. string active_name = switch_name + "_StreamActive";
  656. NodePtr active_node = InsertOp(compute_graph, STREAMACTIVE, active_name, {}, {});
  657. if (active_node == nullptr) {
  658. GELOGE(FAILED, "[Insert][StreamActiveNode] %s for SpecialNodeIteratorCtrl failed.", active_name.c_str());
  659. return FAILED;
  660. }
  661. status = SetStreamLabel(active_node, active_name);
  662. if (status != ge::SUCCESS) {
  663. REPORT_CALL_ERROR("E19999", "Set stream label:%s to op:%s(%s) failed",
  664. active_name.c_str(), active_node->GetName().c_str(), active_node->GetType().c_str());
  665. GELOGE(status, "[Set][StreamLabel] %s to op:%s(%s) failed",
  666. active_name.c_str(), active_node->GetName().c_str(), active_node->GetType().c_str());
  667. return status;
  668. }
  669. GE_IF_BOOL_EXEC(!AttrUtils::SetBool(active_node->GetOpDesc(), ATTR_NAME_IS_LOOP_ACTIVE, true),
  670. REPORT_CALL_ERROR("E19999", "Set Attr:%s to op:%s(%s) failed", ATTR_NAME_IS_LOOP_ACTIVE.c_str(),
  671. active_node->GetName().c_str(), active_node->GetType().c_str());
  672. DOMI_LOGE("[Set][Attr] %s to op:%s(%s) failed", ATTR_NAME_IS_LOOP_ACTIVE.c_str(),
  673. active_node->GetName().c_str(), active_node->GetType().c_str());
  674. return FAILED);
  675. add_ret = GraphUtils::AddEdge(switch_node->GetOutControlAnchor(), active_node->GetInControlAnchor());
  676. if (add_ret != GRAPH_SUCCESS) {
  677. REPORT_CALL_ERROR("E19999", "Add control edge between op:%s(%s) and op:%s(%s) failed",
  678. switch_node->GetName().c_str(), switch_node->GetType().c_str(),
  679. active_node->GetName().c_str(), active_node->GetType().c_str());
  680. GELOGE(FAILED, "[Add][ControlEdge] between op:%s(%s) and op:%s(%s) failed",
  681. switch_node->GetName().c_str(), switch_node->GetType().c_str(),
  682. active_node->GetName().c_str(), active_node->GetType().c_str());
  683. return FAILED;
  684. }
  685. // used for stream assign to find true branch
  686. status = SetActiveLabelList(switch_node, { active_name });
  687. if (status != ge::SUCCESS) {
  688. REPORT_CALL_ERROR("E19999", "Set active label list:%s to op:%s(%s) failed",
  689. active_name.c_str(), switch_node->GetName().c_str(), switch_node->GetType().c_str());
  690. GELOGE(status, "[Set][ActiveLabelList] %s to op:%s(%s) failed",
  691. active_name.c_str(), switch_node->GetName().c_str(), switch_node->GetType().c_str());
  692. return status;
  693. }
  694. // used for stream assign to find active stream
  695. status = SetActiveLabelList(active_node, { loop_pre_node->GetName() });
  696. if (status != ge::SUCCESS) {
  697. REPORT_CALL_ERROR("E19999", "Set active label list:%s to op:%s(%s) failed", loop_pre_node->GetName().c_str(),
  698. active_node->GetName().c_str(), active_node->GetType().c_str());
  699. GELOGE(status, "[Set][ActiveLabelList] %s to op:%s(%s) failed",
  700. loop_pre_node->GetName().c_str(), active_node->GetName().c_str(), active_node->GetType().c_str());
  701. return status;
  702. }
  703. active_nodes_in_iter_loop_.push_back(active_node);
  704. return SUCCESS;
  705. }
  706. } // namespace ge

图引擎模块(GE)是MindSpore的一个子模块,其代码由C++实现,位于前端模块ME和底层硬件之间,起到承接作用。图引擎模块以ME下发的图作为输入,然后进行一系列的深度图优化操作,最后输出一张可以在底层硬件上高效运行的图。GE针对昇腾AI处理器的硬件结构特点,做了特定的优化工作,以此来充分发挥出昇腾AI处理器的强大算力。在进行模型训练/推理时,GE会被自动调用而用户并不感知。GE主要由GE API和GE Core两部分组成,详细的架构图如下所示