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.

hccl_continuous_memcpy_pass.cc 21 kB

4 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
4 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
4 years ago
4 years ago
4 years ago
4 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491
  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/hccl_continuous_memcpy_pass.h"
  17. #include <string>
  18. #include "common/debug/log.h"
  19. #include "framework/common/debug/ge_log.h"
  20. #include "common/ge_inner_error_codes.h"
  21. #include "common/ge/ge_util.h"
  22. #include "framework/common/types.h"
  23. #include "graph/utils/graph_utils.h"
  24. namespace {
  25. const int kAnchorNum = 0;
  26. const int32_t kAnchorAssignRefIndex = 0;
  27. const int32_t kAnchorAssignValueIndex = 1;
  28. } // namespace
  29. namespace ge {
  30. Status HcclContinuousMemcpyPass::Run(ge::ComputeGraphPtr graph) {
  31. GE_CHECK_NOTNULL(graph);
  32. for (const auto &node : graph->GetDirectNode()) {
  33. auto op_desc = node->GetOpDesc();
  34. if (op_desc == nullptr) {
  35. REPORT_INNER_ERROR("E19999", "Node with nullptr op_desc exist in Param graph:%s, check invalid",
  36. graph->GetName().c_str());
  37. GELOGE(INTERNAL_ERROR, "node has no op_desc, node_name : %s.", node->GetName().c_str());
  38. return INTERNAL_ERROR;
  39. }
  40. Status ret = ContinuousInputProcess(graph, node);
  41. if (ret != SUCCESS) {
  42. GELOGE(INTERNAL_ERROR, "failed ProcessBroadcastMemcpy, node_name:%s.", node->GetName().c_str());
  43. return ret;
  44. }
  45. ret = P2pmemInputProcess(graph, node);
  46. if (ret != SUCCESS) {
  47. GELOGE(INTERNAL_ERROR, "failed P2pmemInputProcess, node_name:%s.", node->GetName().c_str());
  48. return ret;
  49. }
  50. }
  51. return SUCCESS;
  52. }
  53. // If broadcast input size is bigger than 1, and input from variable,
  54. // cause by broadcast input memory should be continuous,
  55. // another featuremap mem will be allocated for broadcast input.
  56. // In this condition, move data from variable mem to broadcast input featuremap mem will be executed each step.
  57. // In order to avoid move action out of model, use memcpy node instead of move action code.
  58. Status HcclContinuousMemcpyPass::ContinuousInputProcess(const ComputeGraphPtr &graph, const NodePtr node) {
  59. auto op_desc = node->GetOpDesc();
  60. bool is_input_continuous = false;
  61. (void)ge::AttrUtils::GetBool(op_desc, ATTR_NAME_CONTINUOUS_INPUT, is_input_continuous);
  62. if (is_input_continuous && op_desc->GetInputsSize() > 1) {
  63. GELOGI("continuous input op is:%s.", op_desc->GetName().c_str());
  64. // if input size bigger than one, insert memcpy between var data for support continous mem alloc
  65. for (auto &hccl_in_anchor : node->GetAllInDataAnchors()) {
  66. if (hccl_in_anchor == nullptr) {
  67. continue;
  68. }
  69. auto src_out_anchor = hccl_in_anchor->GetPeerOutAnchor();
  70. if (src_out_anchor == nullptr) {
  71. REPORT_INNER_ERROR("E19999", "Node:%s(%s) input:%d anchor, peer anchor is nullptr, check invalid",
  72. node->GetName().c_str(), node->GetType().c_str(),
  73. hccl_in_anchor->GetIdx());
  74. GELOGE(INTERNAL_ERROR, "hcom op input has no peer anchor, node_name:%s", node->GetName().c_str());
  75. return INTERNAL_ERROR;
  76. }
  77. if (IsDataNode(src_out_anchor->GetOwnerNode()->GetType())) {
  78. Status ret = ModifyEdgeConnection(graph, src_out_anchor, hccl_in_anchor);
  79. if (ret != SUCCESS) {
  80. GELOGE(INTERNAL_ERROR, "Failed to modify the connection.");
  81. return ret;
  82. }
  83. }
  84. }
  85. }
  86. return SUCCESS;
  87. }
  88. // if input is var type, and node input need p2p mem, then memcpy should be insert between the two
  89. Status HcclContinuousMemcpyPass::P2pmemInputProcess(const ComputeGraphPtr &graph, const NodePtr node) {
  90. auto op_desc = node->GetOpDesc();
  91. vector<int64_t> input_memory_types;
  92. (void) ge::AttrUtils::GetListInt(op_desc, ATTR_NAME_INPUT_MEM_TYPE_LIST, input_memory_types);
  93. if (input_memory_types.empty()) {
  94. return SUCCESS;
  95. }
  96. for (uint32_t index = 0; index < input_memory_types.size() && index < op_desc->GetInputsSize(); index++) {
  97. if (input_memory_types[index] != RT_MEMORY_P2P_DDR) {
  98. continue;
  99. }
  100. GELOGD("p2p input op is:%s.", op_desc->GetName().c_str());
  101. auto hccl_in_anchor = node->GetInDataAnchor(index);
  102. if (hccl_in_anchor == nullptr) {
  103. continue;
  104. }
  105. auto src_out_anchor = hccl_in_anchor->GetPeerOutAnchor();
  106. if (src_out_anchor == nullptr) {
  107. REPORT_INNER_ERROR("E19999", "Node:%s(%s) input:%u anchor, peer anchor is nullptr, check invalid",
  108. node->GetName().c_str(), node->GetType().c_str(),
  109. index);
  110. GELOGE(INTERNAL_ERROR, "hcom op input has no peer anchor, node_name:%s", node->GetName().c_str());
  111. return INTERNAL_ERROR;
  112. }
  113. if (IsDataNode(src_out_anchor->GetOwnerNode()->GetType())) {
  114. Status ret = ModifyEdgeConnection(graph, src_out_anchor, hccl_in_anchor);
  115. if (ret != SUCCESS) {
  116. GELOGE(INTERNAL_ERROR, "Failed to modify the connection.");
  117. return ret;
  118. }
  119. }
  120. }
  121. return SUCCESS;
  122. }
  123. bool HcclContinuousMemcpyPass::IsDataNode(const std::string& node_type) {
  124. return (node_type == CONSTANTOP) || (node_type == VARIABLE) || (node_type == DATA) || (node_type == CONSTANT);
  125. }
  126. ///
  127. /// @brief Add Identity Node
  128. /// @param [in] ge::ComputeGraphPtr graph
  129. /// @param [in] ge::OutDataAnchorPtr in_node
  130. /// @return ge::NodePtr
  131. ///
  132. NodePtr HcclContinuousMemcpyPass::CreateIdentityNode(const ComputeGraphPtr &graph,
  133. const OutDataAnchorPtr &out_data_anchor) {
  134. GE_CHECK_NOTNULL_EXEC(graph, return nullptr);
  135. NodePtr pre_node = out_data_anchor->GetOwnerNode();
  136. OpDescPtr pre_op_desc = pre_node->GetOpDesc();
  137. if (pre_op_desc == nullptr) {
  138. REPORT_INNER_ERROR("E19999", "OpDesc in node is nullptr, check invalid");
  139. GELOGE(INTERNAL_ERROR, "OpDesc of pre node is invalid.");
  140. return nullptr;
  141. }
  142. std::string node_name = pre_node->GetName() + "_" + IDENTITY;
  143. node_name = CheckDuplicateName(node_name);
  144. OpDescPtr op_desc = MakeShared<OpDesc>(node_name.c_str(), IDENTITY);
  145. if (op_desc == nullptr) {
  146. REPORT_CALL_ERROR("E19999", "New OpDesc failed");
  147. GELOGE(INTERNAL_ERROR, "Create Identity op: MakeShared op_desc fail.");
  148. return nullptr;
  149. }
  150. GELOGI("Create Identity op:%s.", op_desc->GetName().c_str());
  151. graphStatus ret = op_desc->AddInputDesc("x", pre_op_desc->GetOutputDesc(out_data_anchor->GetIdx()));
  152. if (ret != GRAPH_SUCCESS) {
  153. REPORT_CALL_ERROR("E19999", "Add input desc to op:%s(%s) failed",
  154. op_desc->GetName().c_str(), op_desc->GetType().c_str());
  155. GELOGE(INTERNAL_ERROR, "Create Identity op: add input desc fail.");
  156. return nullptr;
  157. }
  158. ret = op_desc->AddOutputDesc("y", pre_op_desc->GetOutputDesc(out_data_anchor->GetIdx()));
  159. if (ret != GRAPH_SUCCESS) {
  160. REPORT_CALL_ERROR("E19999", "Add output desc to op:%s(%s) failed",
  161. op_desc->GetName().c_str(), op_desc->GetType().c_str());
  162. GELOGE(INTERNAL_ERROR, "Create Identity op: add output desc fail.");
  163. return nullptr;
  164. }
  165. // because history reason ,this pass can not do work after constant fold so mark it
  166. (void)AttrUtils::SetBool(op_desc, ATTR_NO_NEED_CONSTANT_FOLDING, false);
  167. NodePtr memcpy_node = graph->AddNode(op_desc);
  168. if (memcpy_node == nullptr) {
  169. REPORT_CALL_ERROR("E19999", "Add node:%s(%s) to graph:%s failed",
  170. op_desc->GetName().c_str(), op_desc->GetType().c_str(), graph->GetName().c_str());
  171. GELOGE(INTERNAL_ERROR, "Insert Identity node fail.");
  172. return nullptr;
  173. }
  174. return memcpy_node;
  175. }
  176. ///
  177. /// @brief Check duplicate node_name
  178. /// @param [in] std::string& node_name
  179. /// @return std::string
  180. ///
  181. std::string HcclContinuousMemcpyPass::CheckDuplicateName(const std::string &node_name) {
  182. std::string tmp_name = node_name;
  183. auto iter = node_num_map_.find(tmp_name);
  184. if (iter != node_num_map_.end()) {
  185. tmp_name = tmp_name + "_" + std::to_string(iter->second);
  186. (iter->second)++;
  187. } else {
  188. node_num_map_[tmp_name] = 1;
  189. }
  190. return tmp_name;
  191. }
  192. ///
  193. /// @brief Modify edge connection
  194. /// @param [in] ComputeGraphPtr graph
  195. /// @param [in] OutDataAnchorPtr src_out_anchor
  196. /// @param [in] InDataAnchorPtr hccl_in_anchor
  197. /// @return status
  198. ///
  199. Status HcclContinuousMemcpyPass::ModifyEdgeConnection(const ComputeGraphPtr &graph,
  200. const OutDataAnchorPtr &src_out_anchor,
  201. const InDataAnchorPtr &hccl_in_anchor) {
  202. GE_CHECK_NOTNULL(src_out_anchor->GetOwnerNode());
  203. GE_CHECK_NOTNULL(hccl_in_anchor->GetOwnerNode());
  204. Status ret = InsertIdentityBeforeHccl(graph, src_out_anchor, hccl_in_anchor);
  205. if (ret != SUCCESS) {
  206. GELOGE(INTERNAL_ERROR, "add identity failed, var_node:%s, hccl_node:%s.",
  207. src_out_anchor->GetOwnerNode()->GetName().c_str(),
  208. hccl_in_anchor->GetOwnerNode()->GetName().c_str());
  209. return ret;
  210. }
  211. ret = InsertAssignAfterBroadcastIfNeed(graph, src_out_anchor, hccl_in_anchor);
  212. if (ret != SUCCESS) {
  213. GELOGE(INTERNAL_ERROR, "add assign failed, var_node:%s, hccl_node:%s.",
  214. src_out_anchor->GetOwnerNode()->GetName().c_str(),
  215. hccl_in_anchor->GetOwnerNode()->GetName().c_str());
  216. return ret;
  217. }
  218. return SUCCESS;
  219. }
  220. ///
  221. /// @brief Insert Identity node Between Hccl node and variable
  222. /// @param [in] ComputeGraphPtr graph
  223. /// @param [in] OutDataAnchorPtr src_out_anchor
  224. /// @param [in] InDataAnchorPtr hccl_in_anchor
  225. /// @return status
  226. ///
  227. Status HcclContinuousMemcpyPass::InsertIdentityBeforeHccl(const ComputeGraphPtr &graph,
  228. const OutDataAnchorPtr &src_out_anchor,
  229. const InDataAnchorPtr &hccl_in_anchor) {
  230. GELOGI("Between op %s and op %s need insert memcpy async op.", src_out_anchor->GetOwnerNode()->GetName().c_str(),
  231. hccl_in_anchor->GetOwnerNode()->GetName().c_str());
  232. NodePtr memcpy_node = CreateIdentityNode(graph, src_out_anchor);
  233. GE_CHECK_NOTNULL(memcpy_node);
  234. Status ret1 = src_out_anchor->Unlink(hccl_in_anchor);
  235. if (ret1 != SUCCESS) {
  236. REPORT_CALL_ERROR("E19999",
  237. "Op:%s(%s) out index:%d unlink from op:%s(%s) in index:%d failed",
  238. src_out_anchor->GetOwnerNode()->GetName().c_str(),
  239. src_out_anchor->GetOwnerNode()->GetType().c_str(), src_out_anchor->GetIdx(),
  240. hccl_in_anchor->GetOwnerNode()->GetName().c_str(),
  241. hccl_in_anchor->GetOwnerNode()->GetType().c_str(),
  242. hccl_in_anchor->GetIdx());
  243. GELOGE(INTERNAL_ERROR, "The op %s Unlink anchor %s fail.", src_out_anchor->GetOwnerNode()->GetName().c_str(),
  244. hccl_in_anchor->GetOwnerNode()->GetName().c_str());
  245. return FAILED;
  246. }
  247. auto out_data_anchor_0 = memcpy_node->GetOutDataAnchor(kAnchorNum);
  248. GE_CHECK_NOTNULL(out_data_anchor_0);
  249. ret1 = out_data_anchor_0->LinkTo(hccl_in_anchor);
  250. if (ret1 != SUCCESS) {
  251. REPORT_CALL_ERROR("E19999",
  252. "Op:%s(%s) out index:%d link to op:%s(%s) in index:%d failed",
  253. out_data_anchor_0->GetOwnerNode()->GetName().c_str(),
  254. out_data_anchor_0->GetOwnerNode()->GetType().c_str(), out_data_anchor_0->GetIdx(),
  255. hccl_in_anchor->GetOwnerNode()->GetName().c_str(),
  256. hccl_in_anchor->GetOwnerNode()->GetType().c_str(),
  257. hccl_in_anchor->GetIdx());
  258. GELOGE(INTERNAL_ERROR, "The op %s link anchor %s fail.", memcpy_node->GetName().c_str(),
  259. hccl_in_anchor->GetOwnerNode()->GetName().c_str());
  260. return FAILED;
  261. }
  262. Status ret = src_out_anchor->LinkTo(memcpy_node->GetInDataAnchor(kAnchorNum));
  263. if (ret != SUCCESS) {
  264. REPORT_CALL_ERROR("E19999",
  265. "Op:%s(%s) out index:%d link to op:%s(%s) in index:%u failed",
  266. src_out_anchor->GetOwnerNode()->GetName().c_str(),
  267. src_out_anchor->GetOwnerNode()->GetType().c_str(), src_out_anchor->GetIdx(),
  268. memcpy_node->GetName().c_str(), memcpy_node->GetType().c_str(),
  269. kAnchorNum);
  270. GELOGE(INTERNAL_ERROR, "The op %s link anchor %s fail.", src_out_anchor->GetOwnerNode()->GetName().c_str(),
  271. memcpy_node->GetName().c_str());
  272. return FAILED;
  273. }
  274. return SUCCESS;
  275. }
  276. ///
  277. /// @brief Insert assign node after broadcast node and variable to refresh variable data
  278. /// @param [in] ComputeGraphPtr graph
  279. /// @param [in] OutDataAnchorPtr var_out_anchor
  280. /// @param [in] InDataAnchorPtr hccl_in_anchor
  281. /// @return status
  282. ///
  283. Status HcclContinuousMemcpyPass::InsertAssignAfterBroadcastIfNeed(const ComputeGraphPtr &graph,
  284. const OutDataAnchorPtr &var_out_anchor,
  285. const InDataAnchorPtr &hccl_in_anchor) {
  286. if (hccl_in_anchor->GetOwnerNode()->GetType() != HCOMBROADCAST) {
  287. GELOGD("%s not broadcast, no need to insert assign node", hccl_in_anchor->GetOwnerNode()->GetName().c_str());
  288. return SUCCESS;
  289. }
  290. if (var_out_anchor->GetOwnerNode()->GetType() != VARIABLE) {
  291. GELOGD("%s not variable, no need to insert assign node", var_out_anchor->GetOwnerNode()->GetName().c_str());
  292. return SUCCESS;
  293. }
  294. GELOGI("after op %s and op %s need insert assign op.", var_out_anchor->GetOwnerNode()->GetName().c_str(),
  295. hccl_in_anchor->GetOwnerNode()->GetName().c_str());
  296. for (auto peer_in_anchor : var_out_anchor->GetPeerInDataAnchors()) {
  297. if (peer_in_anchor->GetOwnerNode()->GetType() == ASSIGN) {
  298. GELOGD("variable %s out assign node is exist.", var_out_anchor->GetOwnerNode()->GetName().c_str());
  299. return SUCCESS;
  300. }
  301. }
  302. NodePtr assign_node = CreateAssignNode(graph, var_out_anchor);
  303. GE_CHECK_NOTNULL(assign_node);
  304. OutDataAnchorPtr hccl_out_anchor = hccl_in_anchor->GetOwnerNode()->GetOutDataAnchor(hccl_in_anchor->GetIdx());
  305. GE_CHECK_NOTNULL(hccl_out_anchor);
  306. Status ret = hccl_out_anchor->LinkTo(assign_node->GetInDataAnchor(kAnchorAssignValueIndex));
  307. if (ret != SUCCESS) {
  308. REPORT_CALL_ERROR("E19999",
  309. "Op:%s(%s) out index:%d link to op:%s(%s) in index:%u failed",
  310. hccl_out_anchor->GetOwnerNode()->GetName().c_str(),
  311. hccl_out_anchor->GetOwnerNode()->GetType().c_str(), hccl_out_anchor->GetIdx(),
  312. assign_node->GetName().c_str(), assign_node->GetType().c_str(),
  313. kAnchorAssignValueIndex);
  314. GELOGE(INTERNAL_ERROR, "The op %s link anchor %s fail.", hccl_out_anchor->GetOwnerNode()->GetName().c_str(),
  315. assign_node->GetName().c_str());
  316. return FAILED;
  317. }
  318. ret = var_out_anchor->LinkTo(assign_node->GetInDataAnchor(kAnchorAssignRefIndex));
  319. if (ret != SUCCESS) {
  320. REPORT_CALL_ERROR("E19999",
  321. "Op:%s(%s) out index:%d link to op:%s(%s) in index:%u failed",
  322. var_out_anchor->GetOwnerNode()->GetName().c_str(),
  323. var_out_anchor->GetOwnerNode()->GetType().c_str(), var_out_anchor->GetIdx(),
  324. assign_node->GetName().c_str(), assign_node->GetType().c_str(),
  325. kAnchorAssignRefIndex);
  326. GELOGE(INTERNAL_ERROR, "The op %s link anchor %s fail.", var_out_anchor->GetOwnerNode()->GetName().c_str(),
  327. assign_node->GetName().c_str());
  328. return FAILED;
  329. }
  330. // add control edge between assign node and node after broadcast node
  331. OutControlAnchorPtr assign_out_control_anchor = assign_node->GetOutControlAnchor();
  332. GE_CHECK_NOTNULL(assign_out_control_anchor);
  333. for (auto in_data_anchor : hccl_out_anchor->GetPeerInDataAnchors()) {
  334. if (in_data_anchor->GetOwnerNode()->GetName() == assign_node->GetName()) {
  335. continue;
  336. }
  337. ret = assign_out_control_anchor->LinkTo(in_data_anchor->GetOwnerNode()->GetInControlAnchor());
  338. if (ret != SUCCESS) {
  339. REPORT_CALL_ERROR("E19999", "Op:%s(%s) link control to op:%s(%s) failed",
  340. assign_out_control_anchor->GetOwnerNode()->GetName().c_str(),
  341. assign_out_control_anchor->GetOwnerNode()->GetType().c_str(),
  342. in_data_anchor->GetOwnerNode()->GetName().c_str(),
  343. in_data_anchor->GetOwnerNode()->GetType().c_str());
  344. GELOGE(INTERNAL_ERROR, "The op %s link control anchor %s fail.",
  345. assign_out_control_anchor->GetOwnerNode()->GetName().c_str(),
  346. in_data_anchor->GetOwnerNode()->GetName().c_str());
  347. return FAILED;
  348. }
  349. }
  350. for (auto in_control_anchor : hccl_out_anchor->GetOwnerNode()->GetOutControlAnchor()->GetPeerInControlAnchors()) {
  351. if (in_control_anchor->GetOwnerNode()->GetName() == assign_node->GetName()) {
  352. continue;
  353. }
  354. ret = assign_out_control_anchor->LinkTo(in_control_anchor);
  355. if (ret != SUCCESS) {
  356. REPORT_CALL_ERROR("E19999", "Op:%s(%s) link control to op:%s(%s) failed",
  357. assign_out_control_anchor->GetOwnerNode()->GetName().c_str(),
  358. assign_out_control_anchor->GetOwnerNode()->GetType().c_str(),
  359. in_control_anchor->GetOwnerNode()->GetName().c_str(),
  360. in_control_anchor->GetOwnerNode()->GetType().c_str());
  361. GELOGE(INTERNAL_ERROR, "The op %s link control anchor %s fail.",
  362. assign_out_control_anchor->GetOwnerNode()->GetName().c_str(),
  363. in_control_anchor->GetOwnerNode()->GetName().c_str());
  364. return FAILED;
  365. }
  366. }
  367. return SUCCESS;
  368. }
  369. ///
  370. /// @brief create assign Node, add to graph
  371. /// @param [in] ge::ComputeGraphPtr graph
  372. /// @param [in] ge::OutDataAnchorPtr variable node out anchor
  373. /// @return ge::NodePtr
  374. ///
  375. NodePtr HcclContinuousMemcpyPass::CreateAssignNode(const ComputeGraphPtr &graph,
  376. const OutDataAnchorPtr &out_data_anchor) {
  377. GE_CHECK_NOTNULL_EXEC(graph, return nullptr);
  378. NodePtr pre_node = out_data_anchor->GetOwnerNode();
  379. OpDescPtr pre_op_desc = pre_node->GetOpDesc();
  380. if (pre_op_desc == nullptr) {
  381. REPORT_INNER_ERROR("E19999", "OpDesc in node is nullptr, check invalid");
  382. GELOGE(INTERNAL_ERROR, "OpDesc of pre node is invalid.");
  383. return nullptr;
  384. }
  385. std::string node_name = pre_node->GetName() + "_" + ASSIGN;
  386. node_name = CheckDuplicateName(node_name);
  387. OpDescPtr op_desc = MakeShared<OpDesc>(node_name.c_str(), ASSIGN);
  388. if (op_desc == nullptr) {
  389. REPORT_CALL_ERROR("E19999", "New OpDesc failed");
  390. GELOGE(INTERNAL_ERROR, "Create Assign op: MakeShared op_desc fail.");
  391. return nullptr;
  392. }
  393. GELOGI("Create Assign op:%s.", op_desc->GetName().c_str());
  394. if (!AttrUtils::SetBool(op_desc, ATTR_NEED_COMPILE, true)) {
  395. REPORT_CALL_ERROR("E19999", "Set Attr:%s to op:%s(%s) failed",
  396. ATTR_NEED_COMPILE.c_str(),
  397. op_desc->GetName().c_str(), op_desc->GetType().c_str());
  398. GELOGE(INTERNAL_ERROR, "Set ATTR_NEED_COMPILE Attr for node:%s fail.", op_desc->GetName().c_str());
  399. return nullptr;
  400. }
  401. graphStatus ret = op_desc->AddInputDesc("ref", pre_op_desc->GetOutputDesc(out_data_anchor->GetIdx()));
  402. if (ret != GRAPH_SUCCESS) {
  403. REPORT_CALL_ERROR("E19999", "Add input desc to op:%s(%s) failed, name:ref",
  404. op_desc->GetName().c_str(), op_desc->GetType().c_str());
  405. GELOGE(INTERNAL_ERROR, "Create Assign op: add ref input desc fail.");
  406. return nullptr;
  407. }
  408. ret = op_desc->AddInputDesc("value", pre_op_desc->GetOutputDesc(out_data_anchor->GetIdx()));
  409. if (ret != GRAPH_SUCCESS) {
  410. REPORT_CALL_ERROR("E19999", "Add input desc to op:%s(%s) failed, name:value",
  411. op_desc->GetName().c_str(), op_desc->GetType().c_str());
  412. GELOGE(INTERNAL_ERROR, "Create Assign op: add value input desc fail.");
  413. return nullptr;
  414. }
  415. ret = op_desc->AddOutputDesc("ref", pre_op_desc->GetOutputDesc(out_data_anchor->GetIdx()));
  416. if (ret != GRAPH_SUCCESS) {
  417. REPORT_CALL_ERROR("E19999", "Add output desc to op:%s(%s) failed, name:ref",
  418. op_desc->GetName().c_str(), op_desc->GetType().c_str());
  419. GELOGE(INTERNAL_ERROR, "Create Assign op: add output desc fail.");
  420. return nullptr;
  421. }
  422. NodePtr assign_node = graph->AddNode(op_desc);
  423. if (assign_node == nullptr) {
  424. REPORT_CALL_ERROR("E19999", "Add node:%s(%s) to graph:%s failed",
  425. op_desc->GetName().c_str(), op_desc->GetType().c_str(), graph->GetName().c_str());
  426. GELOGE(INTERNAL_ERROR, "Insert Identity node fail.");
  427. return nullptr;
  428. }
  429. return assign_node;
  430. }
  431. ///
  432. /// @brief Clear Status, used for subgraph pass
  433. /// @return SUCCESS
  434. ///
  435. Status HcclContinuousMemcpyPass::ClearStatus() {
  436. node_num_map_.clear();
  437. return SUCCESS;
  438. }
  439. } // namespace ge

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