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.

node_utils.cc 36 kB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005
  1. /**
  2. * Copyright 2019-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/utils/node_utils.h"
  17. #include "graph/utils/op_desc_utils.h"
  18. #include "graph/utils/graph_utils.h"
  19. #include "debug/ge_op_types.h"
  20. #include "debug/ge_util.h"
  21. #include "framework/common/debug/ge_log.h"
  22. #include "graph/anchor.h"
  23. #include "graph/debug/ge_attr_define.h"
  24. #include "graph/types.h"
  25. #include "external/graph/operator.h"
  26. #include "graph/ge_context.h"
  27. #include "graph/runtime_inference_context.h"
  28. #include "graph/utils/op_desc_utils.h"
  29. #include "graph/utils/tensor_utils.h"
  30. #include "graph/utils/tensor_adapter.h"
  31. #include "graph/utils/type_utils.h"
  32. namespace ge {
  33. std::map<NodePtr, std::vector<uint32_t>> NodeUtils::map_send_info_{};
  34. std::map<NodePtr, std::vector<uint32_t>> NodeUtils::map_recv_info_{};
  35. const std::set<std::string> kConstOpTypes = {"Const", "Constant"};
  36. const std::set<std::string> kIfOpTypes = {"If", "_If", "StatelessIf"};
  37. const std::set<std::string> kWhileOpTypes = {"While", "_While", "StatelessWhile"};
  38. const std::set<std::string> kCaseOpTypes = {"Case"};
  39. const std::set<std::string> kForOpTypes = {"For"};
  40. bool OpShapeIsUnknown(const OpDescPtr &desc) {
  41. for (const auto &ptr : desc->GetAllInputsDescPtr()) {
  42. auto ge_shape = ptr->GetShape();
  43. for (const auto &dim : ge_shape.GetDims()) {
  44. if (dim == UNKNOWN_DIM || dim == UNKNOWN_DIM_NUM) {
  45. return true;
  46. }
  47. }
  48. }
  49. for (const auto &ptr : desc->GetAllOutputsDescPtr()) {
  50. auto ge_shape = ptr->GetShape();
  51. for (const auto &dim : ge_shape.GetDims()) {
  52. if (dim == UNKNOWN_DIM || dim == UNKNOWN_DIM_NUM) {
  53. return true;
  54. }
  55. }
  56. }
  57. return false;
  58. }
  59. GE_FUNC_DEV_VISIBILITY GE_FUNC_HOST_VISIBILITY graphStatus NodeUtils::AddSendEventId(const NodePtr &node,
  60. const uint32_t &event_id) {
  61. GE_CHECK_NOTNULL(node);
  62. map_send_info_[node].push_back(event_id);
  63. return GRAPH_SUCCESS;
  64. }
  65. GE_FUNC_DEV_VISIBILITY GE_FUNC_HOST_VISIBILITY graphStatus NodeUtils::AddRecvEventId(const NodePtr &node,
  66. const uint32_t &event_id) {
  67. GE_CHECK_NOTNULL(node);
  68. map_recv_info_[node].push_back(event_id);
  69. return GRAPH_SUCCESS;
  70. }
  71. GE_FUNC_DEV_VISIBILITY GE_FUNC_HOST_VISIBILITY graphStatus
  72. NodeUtils::GetSendEventIdList(const NodePtr &node, std::vector<uint32_t> &vec_send) {
  73. GE_CHECK_NOTNULL(node);
  74. auto find = map_send_info_.find(node);
  75. if (find == map_send_info_.end()) {
  76. return GRAPH_FAILED;
  77. } else {
  78. vec_send = find->second;
  79. return GRAPH_SUCCESS;
  80. }
  81. }
  82. GE_FUNC_DEV_VISIBILITY GE_FUNC_HOST_VISIBILITY graphStatus
  83. NodeUtils::GetRecvEventIdList(const NodePtr &node, std::vector<uint32_t> &vec_recv) {
  84. GE_CHECK_NOTNULL(node);
  85. auto find = map_recv_info_.find(node);
  86. if (find == map_recv_info_.end()) {
  87. return GRAPH_FAILED;
  88. } else {
  89. vec_recv = find->second;
  90. return GRAPH_SUCCESS;
  91. }
  92. }
  93. GE_FUNC_DEV_VISIBILITY GE_FUNC_HOST_VISIBILITY graphStatus NodeUtils::ClearSendInfo() {
  94. map_send_info_.clear();
  95. return GRAPH_SUCCESS;
  96. }
  97. GE_FUNC_DEV_VISIBILITY GE_FUNC_HOST_VISIBILITY graphStatus NodeUtils::ClearRecvInfo() {
  98. map_recv_info_.clear();
  99. return GRAPH_SUCCESS;
  100. }
  101. graphStatus NodeUtils::GetSingleOutputNodeOfNthLayer(const NodePtr &src, int depth, NodePtr &dst) {
  102. GE_CHECK_NOTNULL(src);
  103. NodePtr cur_ptr;
  104. if (depth < 1) {
  105. return GRAPH_FAILED;
  106. }
  107. for (int i = 0; i < depth; i++) {
  108. if (src->GetOutDataNodes().size() != 1) {
  109. return GRAPH_FAILED;
  110. }
  111. cur_ptr = src->GetOutDataNodes().at(0);
  112. GE_CHECK_NOTNULL(cur_ptr);
  113. }
  114. dst = cur_ptr;
  115. return GRAPH_SUCCESS;
  116. }
  117. graphStatus NodeUtils::GetDataOutAnchorAndControlInAnchor(const NodePtr &node_ptr, OutDataAnchorPtr &out_data,
  118. InControlAnchorPtr &in_control) {
  119. GE_CHECK_NOTNULL(node_ptr);
  120. for (const auto &p : node_ptr->GetAllOutDataAnchors()) {
  121. GE_CHK_BOOL_EXEC((p != nullptr), continue, "GetAllOutDataAnchors is nullptr");
  122. for (const auto &p_in : p->GetPeerInControlAnchors()) {
  123. GE_CHK_BOOL_EXEC((p_in != nullptr), continue, "GetPeerInDataAnchors is nullptr");
  124. out_data = p;
  125. in_control = p_in;
  126. return GRAPH_SUCCESS;
  127. }
  128. }
  129. return GRAPH_FAILED;
  130. }
  131. graphStatus NodeUtils::ClearInDataAnchor(const NodePtr &node_ptr, const InDataAnchorPtr &in_data_anchor) {
  132. GE_CHK_BOOL_EXEC(node_ptr != nullptr && in_data_anchor != nullptr, return GRAPH_FAILED,
  133. "node or in_data_anchor is nullptr");
  134. bool find_flag = false;
  135. uint32_t index = 0;
  136. vector<InDataAnchorPtr>::iterator it = node_ptr->in_data_anchors_.end();
  137. for (const auto &tmp : node_ptr->in_data_anchors_) {
  138. if (tmp == in_data_anchor) {
  139. find_flag = true;
  140. auto iter = node_ptr->in_data_anchors_.begin() + index;
  141. if (iter != node_ptr->in_data_anchors_.end()) {
  142. it = node_ptr->in_data_anchors_.erase(iter);
  143. }
  144. break;
  145. }
  146. index++;
  147. }
  148. for (; it != node_ptr->in_data_anchors_.end(); ++it) {
  149. (*it)->SetIdx(index);
  150. index++;
  151. }
  152. if (!find_flag) {
  153. return GRAPH_FAILED;
  154. }
  155. return GRAPH_SUCCESS;
  156. }
  157. GE_FUNC_DEV_VISIBILITY GE_FUNC_HOST_VISIBILITY graphStatus NodeUtils::SetAllAnchorStatus(const NodePtr &node_ptr) {
  158. GE_CHK_BOOL_EXEC(node_ptr != nullptr, return GRAPH_FAILED, "node is nullptr");
  159. GE_CHK_BOOL_EXEC(SetAllAnchorStatus(*node_ptr) == GRAPH_SUCCESS, return GRAPH_FAILED, "set all anchor status failed");
  160. return GRAPH_SUCCESS;
  161. }
  162. graphStatus NodeUtils::SetAllAnchorStatus(Node &node) {
  163. node.anchor_status_updated_ = true;
  164. return GRAPH_SUCCESS;
  165. }
  166. GE_FUNC_DEV_VISIBILITY GE_FUNC_HOST_VISIBILITY bool NodeUtils::IsAnchorStatusSet(const NodePtr &node_ptr) {
  167. GE_CHK_BOOL_EXEC(node_ptr != nullptr, return false, "node is nullptr");
  168. return IsAnchorStatusSet(*node_ptr);
  169. }
  170. bool NodeUtils::IsAnchorStatusSet(const Node &node) { return node.anchor_status_updated_; }
  171. graphStatus NodeUtils::MoveOutputEdges(const NodePtr &origin_node, const NodePtr &new_node) {
  172. if ((origin_node == nullptr) || (new_node == nullptr)) {
  173. return GRAPH_FAILED;
  174. }
  175. auto origin_out_data_anchors = origin_node->GetAllOutDataAnchors();
  176. auto new_out_data_anchors = new_node->GetAllOutDataAnchors();
  177. if (origin_out_data_anchors.size() != new_out_data_anchors.size()) {
  178. return GRAPH_FAILED;
  179. }
  180. for (size_t i = 0; i < origin_out_data_anchors.size(); ++i) {
  181. for (const auto &peer_anchor : origin_out_data_anchors.at(i)->GetPeerInDataAnchors()) {
  182. GE_CHK_BOOL_EXEC(origin_out_data_anchors.at(i)->Unlink(peer_anchor) == GRAPH_SUCCESS, continue,
  183. "unlink peer_anchor failed");
  184. GE_CHK_BOOL_EXEC(new_out_data_anchors.at(i)->LinkTo(peer_anchor) == GRAPH_SUCCESS, continue,
  185. "linkto peer_anchor failed");
  186. }
  187. for (const auto &peer_anchor : origin_out_data_anchors.at(i)->GetPeerInControlAnchors()) {
  188. GE_CHK_BOOL_EXEC(origin_out_data_anchors.at(i)->Unlink(peer_anchor) == GRAPH_SUCCESS, continue,
  189. "unlink peer_anchor failed");
  190. GE_CHK_BOOL_EXEC(new_out_data_anchors.at(i)->LinkTo(peer_anchor) == GRAPH_SUCCESS, continue,
  191. "linkto peer_anchor failed");
  192. }
  193. }
  194. auto origin_out_control_anchor = origin_node->GetOutControlAnchor();
  195. GE_CHECK_NOTNULL(origin_out_control_anchor);
  196. auto new_out_control_anchor = new_node->GetOutControlAnchor();
  197. GE_CHECK_NOTNULL(new_out_control_anchor);
  198. for (const auto &peer_anchor : origin_out_control_anchor->GetPeerInControlAnchors()) {
  199. GE_CHK_BOOL_EXEC(new_out_control_anchor->LinkTo(peer_anchor) == GRAPH_SUCCESS, continue,
  200. "linkto peer_anchor failed");
  201. }
  202. for (const auto &peer_anchor : origin_out_control_anchor->GetPeerInDataAnchors()) {
  203. GE_CHK_BOOL_EXEC(new_out_control_anchor->LinkTo(peer_anchor) == GRAPH_SUCCESS, continue,
  204. "linkto peer_anchor failed");
  205. }
  206. origin_out_control_anchor->UnlinkAll();
  207. return GRAPH_SUCCESS;
  208. }
  209. bool NodeUtils::IsConst(const Node &node) {
  210. auto src_node_type = node.GetType();
  211. bool is_const = ((src_node_type == CONSTANT) || (src_node_type == CONSTANTOP));
  212. return is_const;
  213. }
  214. void NodeUtils::UpdateIsInputConst(const NodePtr &node_ptr) {
  215. if (node_ptr == nullptr) {
  216. GELOGE(GRAPH_FAILED, "node is null");
  217. return;
  218. }
  219. UpdateIsInputConst(*node_ptr);
  220. }
  221. ///
  222. /// update is_input_const
  223. /// @param node
  224. /// @return void
  225. ///
  226. void NodeUtils::UpdateIsInputConst(Node &node) {
  227. std::vector<bool> is_input_const;
  228. size_t anchor_num = node.GetAllInDataAnchors().size();
  229. for (size_t i = 0; i < anchor_num; i++) {
  230. auto in_anchor = node.GetInDataAnchor(static_cast<int>(i));
  231. if (in_anchor == nullptr) {
  232. is_input_const.push_back(false);
  233. continue;
  234. }
  235. auto peer_out_anchor = in_anchor->GetPeerOutAnchor();
  236. if (peer_out_anchor == nullptr) {
  237. is_input_const.push_back(false);
  238. continue;
  239. }
  240. auto src_node = peer_out_anchor->GetOwnerNode();
  241. if (src_node == nullptr) {
  242. is_input_const.push_back(false);
  243. continue;
  244. }
  245. if (IsConst(*(src_node))) {
  246. is_input_const.push_back(true);
  247. } else {
  248. is_input_const.push_back(false);
  249. }
  250. }
  251. if (node.GetOpDesc() == nullptr) {
  252. GELOGE(GRAPH_FAILED, "Node get opdesc is nullptr");
  253. return;
  254. }
  255. node.GetOpDesc()->SetIsInputConst(is_input_const);
  256. }
  257. void NodeUtils::UnlinkAll(const Node &node) {
  258. for (const auto &anchor : node.GetAllOutAnchors()) {
  259. anchor->UnlinkAll();
  260. }
  261. for (const auto &anchor : node.GetAllInAnchors()) {
  262. anchor->UnlinkAll();
  263. }
  264. }
  265. GE_FUNC_DEV_VISIBILITY GE_FUNC_HOST_VISIBILITY graphStatus NodeUtils::UpdatePeerNodeInputDesc(const NodePtr &node_ptr) {
  266. if (node_ptr == nullptr) {
  267. GELOGE(GRAPH_FAILED, "Nodeptr is nullptr");
  268. return GRAPH_FAILED;
  269. }
  270. auto op_desc = node_ptr->GetOpDesc();
  271. if (op_desc == nullptr) {
  272. return GRAPH_FAILED;
  273. }
  274. bool is_unknown_graph = node_ptr->GetOwnerComputeGraph()->GetGraphUnknownFlag();
  275. if (is_unknown_graph) {
  276. return GRAPH_SUCCESS;
  277. }
  278. for (const auto &out_anchor : node_ptr->GetAllOutDataAnchors()) {
  279. auto output_tensor = op_desc->MutableOutputDesc(out_anchor->GetIdx());
  280. auto out_dims = output_tensor->GetShape().GetDims();
  281. auto out_dtype = output_tensor->GetDataType();
  282. ge::TensorUtils::SetRealDimCnt(*output_tensor, static_cast<uint32_t>(output_tensor->GetShape().GetDims().size()));
  283. output_tensor->SetOriginShape(output_tensor->GetShape());
  284. output_tensor->SetOriginDataType(output_tensor->GetDataType());
  285. GELOGD("node name is %s, origin shape is %ld, origin format is %s, origin data type is %s",
  286. node_ptr->GetName().c_str(), output_tensor->GetOriginShape().GetShapeSize(),
  287. TypeUtils::FormatToSerialString(output_tensor->GetOriginFormat()).c_str(),
  288. TypeUtils::DataTypeToSerialString(output_tensor->GetOriginDataType()).c_str());
  289. for (const auto &peer_anchor : out_anchor->GetPeerInDataAnchors()) {
  290. if (peer_anchor->GetOwnerNode()->GetOpDesc() == nullptr) {
  291. GELOGE(GRAPH_FAILED, "peer_anchor opdesc is null");
  292. continue;
  293. }
  294. auto peer_input_desc = peer_anchor->GetOwnerNode()->GetOpDesc()->MutableInputDesc(peer_anchor->GetIdx());
  295. if (peer_input_desc == nullptr) {
  296. GELOGE(GRAPH_FAILED, "peer_input_desc is nullptr");
  297. continue;
  298. }
  299. // check shape and dtype continuity. do not stop process
  300. auto peer_input_dims = peer_input_desc->GetShape().GetDims();
  301. auto peer_input_dtype = peer_input_desc->GetDataType();
  302. if (out_dtype != peer_input_dtype) {
  303. GELOGW(
  304. "current node [%s] [%d]\'th out_dtype is [%s].peer input node [%s] [%d]\'th "
  305. "input_dtype is [%s].The two dtype should be same! Please check graph and fix it",
  306. node_ptr->GetName().c_str(), out_anchor->GetIdx(), TypeUtils::DataTypeToSerialString(out_dtype).c_str(),
  307. peer_anchor->GetOwnerNode()->GetName().c_str(), peer_anchor->GetIdx(),
  308. TypeUtils::DataTypeToSerialString(peer_input_dtype).c_str());
  309. } else if ((!peer_input_dims.empty()) && (out_dims != peer_input_dims)) {
  310. string out_shape_str, peer_in_shape_str;
  311. out_shape_str += "[";
  312. for (int64_t dim : out_dims) {
  313. out_shape_str += std::to_string(dim) + " ";
  314. }
  315. out_shape_str += "]";
  316. peer_in_shape_str += "[";
  317. for (int64_t dim : peer_input_dims) {
  318. peer_in_shape_str += std::to_string(dim) + " ";
  319. }
  320. peer_in_shape_str += "]";
  321. GELOGW(
  322. "current node [%s] [%d]\'th out_shape is [%s].peer input node [%s] [%d]\'th "
  323. "input_shape is [%s].The two shape should be same! Please check graph and fix it",
  324. node_ptr->GetName().c_str(), out_anchor->GetIdx(), out_shape_str.c_str(),
  325. peer_anchor->GetOwnerNode()->GetName().c_str(), peer_anchor->GetIdx(), peer_in_shape_str.c_str());
  326. }
  327. GELOGI("Peer input opdesc name is %s, need to flush: shape size is %zu, datatype is %d, original datatype is %d",
  328. peer_anchor->GetOwnerNode()->GetOpDesc()->GetName().c_str(), output_tensor->GetShape().GetDimNum(),
  329. output_tensor->GetDataType(), output_tensor->GetOriginDataType());
  330. peer_input_desc->SetOriginShape(output_tensor->GetOriginShape());
  331. peer_input_desc->SetShape(output_tensor->GetShape());
  332. peer_input_desc->SetDataType(output_tensor->GetDataType());
  333. peer_input_desc->SetOriginDataType(output_tensor->GetOriginDataType());
  334. std::vector<std::pair<int64_t, int64_t>> shape_range;
  335. (void)output_tensor->GetShapeRange(shape_range);
  336. peer_input_desc->SetShapeRange(shape_range);
  337. ge::TensorUtils::SetRealDimCnt(*peer_input_desc,
  338. static_cast<uint32_t>(output_tensor->GetShape().GetDims().size()));
  339. GELOGI("Peer input opdesc name is %s, shape size is %zu, datatype is %d, original datatype is %d",
  340. peer_anchor->GetOwnerNode()->GetOpDesc()->GetName().c_str(), peer_input_desc->GetShape().GetDimNum(),
  341. peer_input_desc->GetDataType(), peer_input_desc->GetOriginDataType());
  342. }
  343. }
  344. return GRAPH_SUCCESS;
  345. }
  346. GE_FUNC_DEV_VISIBILITY GE_FUNC_HOST_VISIBILITY graphStatus NodeUtils::AppendInputAnchor(const NodePtr &node,
  347. uint32_t num) {
  348. if (node == nullptr) {
  349. GELOGE(GRAPH_FAILED, "Input node is null");
  350. return GRAPH_FAILED;
  351. }
  352. GeTensorDesc data_desc(GeShape(), FORMAT_ND, DT_FLOAT);
  353. const auto &op_desc = node->GetOpDesc();
  354. for (size_t i = op_desc->GetInputsSize(); i < num; ++i) {
  355. if (op_desc->AddInputDesc(data_desc) != GRAPH_SUCCESS) {
  356. GELOGE(GRAPH_FAILED, "Add input desc failed");
  357. return GRAPH_FAILED;
  358. }
  359. auto anchor = ComGraphMakeShared<InDataAnchor>(node, i);
  360. if (anchor == nullptr) {
  361. GELOGE(OUT_OF_MEMORY, "Current in data anchor is null, make shared_ptr failed.");
  362. return GRAPH_FAILED;
  363. }
  364. node->in_data_anchors_.push_back(anchor);
  365. }
  366. return GRAPH_SUCCESS;
  367. }
  368. GE_FUNC_DEV_VISIBILITY GE_FUNC_HOST_VISIBILITY graphStatus NodeUtils::RemoveInputAnchor(const NodePtr &node,
  369. uint32_t num) {
  370. if (node == nullptr) {
  371. GELOGE(GRAPH_FAILED, "Input node is null");
  372. return GRAPH_FAILED;
  373. }
  374. const auto &op_desc = node->GetOpDesc();
  375. while (op_desc->GetInputsSize() > num) {
  376. if (!OpDescUtils::ClearInputDesc(op_desc, num)) {
  377. return GRAPH_FAILED;
  378. }
  379. }
  380. auto input_names = op_desc->GetAllInputName();
  381. (void)op_desc->UpdateInputName(input_names);
  382. auto is_input_const = op_desc->GetIsInputConst();
  383. is_input_const.resize(num);
  384. op_desc->SetIsInputConst(is_input_const);
  385. while (node->in_data_anchors_.size() > num) {
  386. node->in_data_anchors_.pop_back();
  387. }
  388. return GRAPH_SUCCESS;
  389. }
  390. GE_FUNC_DEV_VISIBILITY GE_FUNC_HOST_VISIBILITY graphStatus NodeUtils::AppendOutputAnchor(const NodePtr &node,
  391. uint32_t num) {
  392. if (node == nullptr) {
  393. GELOGE(GRAPH_FAILED, "Input node is null");
  394. return GRAPH_FAILED;
  395. }
  396. GeTensorDesc data_desc(GeShape(), FORMAT_ND, DT_FLOAT);
  397. const OpDescPtr &op_desc = node->GetOpDesc();
  398. for (size_t i = op_desc->GetOutputsSize(); i < num; ++i) {
  399. if (op_desc->AddOutputDesc(data_desc) != GRAPH_SUCCESS) {
  400. GELOGE(GRAPH_FAILED, "Add output desc failed");
  401. return GRAPH_FAILED;
  402. }
  403. auto anchor = ComGraphMakeShared<OutDataAnchor>(node, i);
  404. if (anchor == nullptr) {
  405. GELOGE(OUT_OF_MEMORY, "Current out data anchor is null, make shared_ptr failed.");
  406. return GRAPH_FAILED;
  407. }
  408. node->out_data_anchors_.push_back(anchor);
  409. }
  410. return GRAPH_SUCCESS;
  411. }
  412. GE_FUNC_DEV_VISIBILITY GE_FUNC_HOST_VISIBILITY graphStatus NodeUtils::RemoveOutputAnchor(const NodePtr &node,
  413. uint32_t num) {
  414. if (node == nullptr) {
  415. GELOGE(GRAPH_FAILED, "Input node is null");
  416. return GRAPH_FAILED;
  417. }
  418. const auto &op_desc = node->GetOpDesc();
  419. auto output_names = op_desc->GetAllOutputName();
  420. while (op_desc->GetOutputsSize() > num) {
  421. if (!OpDescUtils::ClearOutputDesc(op_desc, num)) {
  422. return GRAPH_FAILED;
  423. }
  424. }
  425. (void)op_desc->UpdateOutputName(output_names);
  426. while (node->out_data_anchors_.size() > num) {
  427. node->out_data_anchors_.pop_back();
  428. }
  429. return GRAPH_SUCCESS;
  430. }
  431. bool NodeUtils::IsInNodesEmpty(const Node &node) {
  432. for (const auto &in_anchor : node.in_data_anchors_) {
  433. if (in_anchor != nullptr) {
  434. auto out_anchor = in_anchor->GetPeerOutAnchor();
  435. if (out_anchor != nullptr) {
  436. if (out_anchor->GetOwnerNode() != nullptr) {
  437. return false;
  438. }
  439. }
  440. }
  441. }
  442. if ((node.in_control_anchor_ != nullptr) && (!node.in_control_anchor_->IsPeerOutAnchorsEmpty())) {
  443. auto peer_out_control_anchors = node.in_control_anchor_->GetPeerOutControlAnchors();
  444. for (const auto &out_control_anchor : peer_out_control_anchors) {
  445. if (out_control_anchor != nullptr) {
  446. if (out_control_anchor->GetOwnerNode() != nullptr) {
  447. return false;
  448. }
  449. }
  450. }
  451. }
  452. return true;
  453. }
  454. GeTensorDesc NodeUtils::GetOutputDesc(const Node &node, uint32_t index) {
  455. auto desc = node.GetOpDesc();
  456. if (desc == nullptr) {
  457. return GeTensorDesc();
  458. }
  459. return desc->GetOutputDesc(index);
  460. }
  461. GeTensorDesc NodeUtils::GetInputDesc(const Node &node, uint32_t index) {
  462. auto desc = node.GetOpDesc();
  463. if (desc == nullptr) {
  464. return GeTensorDesc();
  465. }
  466. return desc->GetInputDesc(index);
  467. }
  468. graphStatus NodeUtils::UpdateOutputShape(const Node &node, uint32_t index, const GeShape &shape) {
  469. auto desc = node.GetOpDesc();
  470. if (desc == nullptr) {
  471. return GRAPH_PARAM_INVALID;
  472. }
  473. auto output_desc = desc->MutableOutputDesc(index);
  474. if (output_desc == nullptr) {
  475. return GRAPH_PARAM_INVALID;
  476. }
  477. output_desc->SetShape(shape);
  478. return GRAPH_SUCCESS;
  479. }
  480. graphStatus NodeUtils::UpdateInputShape(const Node &node, uint32_t index, const GeShape &shape) {
  481. auto desc = node.GetOpDesc();
  482. if (desc == nullptr) {
  483. return GRAPH_PARAM_INVALID;
  484. }
  485. auto input_desc = desc->MutableInputDesc(index);
  486. if (input_desc == nullptr) {
  487. return GRAPH_PARAM_INVALID;
  488. }
  489. input_desc->SetShape(shape);
  490. return GRAPH_SUCCESS;
  491. }
  492. graphStatus NodeUtils::GetNodeUnknownShapeStatus(const Node &node, bool &is_unknow) {
  493. auto desc = node.GetOpDesc();
  494. GE_CHECK_NOTNULL(desc);
  495. // check self
  496. is_unknow = OpShapeIsUnknown(desc);
  497. if (is_unknow) {
  498. return GRAPH_SUCCESS;
  499. }
  500. auto sub_graph_names = desc->GetSubgraphInstanceNames();
  501. if (sub_graph_names.empty()) {
  502. return GRAPH_SUCCESS;
  503. } else {
  504. auto owner_graph = node.GetOwnerComputeGraph();
  505. GE_CHECK_NOTNULL(owner_graph);
  506. auto root_graph = GraphUtils::FindRootGraph(node.GetOwnerComputeGraph());
  507. if (root_graph == nullptr) {
  508. GE_LOGE("Node %s gets null root graph", node.GetName().c_str());
  509. return GRAPH_PARAM_INVALID;
  510. }
  511. for (auto &sub_graph_name : sub_graph_names) {
  512. auto sub_graph = root_graph->GetSubgraph(sub_graph_name);
  513. GE_CHECK_NOTNULL(sub_graph);
  514. for (const auto &node_ptr : sub_graph->GetDirectNode()) {
  515. auto status = GetNodeUnknownShapeStatus(*node_ptr, is_unknow);
  516. if (status != GRAPH_SUCCESS) {
  517. GE_LOGE("get node unknown shape status failed!");
  518. return status;
  519. }
  520. if (is_unknow) {
  521. return GRAPH_SUCCESS;
  522. }
  523. }
  524. }
  525. }
  526. return GRAPH_SUCCESS;
  527. }
  528. graphStatus NodeUtils::GetInputConstData(const ConstNodePtr &node_ptr, const string &dst_name, GeTensorPtr &ge_tensor) {
  529. GE_CHECK_NOTNULL(node_ptr);
  530. return NodeUtils::GetInputConstData(*node_ptr, dst_name, ge_tensor);
  531. }
  532. graphStatus NodeUtils::GetInputConstData(const Node &node, const string &dst_name, GeTensorPtr &ge_tensor) {
  533. // For inner compute graph
  534. auto op_desc = node.GetOpDesc();
  535. GE_CHECK_NOTNULL(op_desc);
  536. auto index = op_desc->GetInputIndexByName(dst_name);
  537. auto in_data_anchor = node.GetInDataAnchor(index);
  538. GE_CHECK_NOTNULL(in_data_anchor);
  539. auto out_data_anchor = in_data_anchor->GetPeerOutAnchor();
  540. GE_CHECK_NOTNULL(out_data_anchor);
  541. auto peer_node = out_data_anchor->GetOwnerNode();
  542. GE_CHECK_NOTNULL(peer_node);
  543. auto peer_op_desc = peer_node->GetOpDesc();
  544. GE_CHECK_NOTNULL(peer_op_desc);
  545. auto peer_op_type = peer_op_desc->GetType();
  546. if (peer_op_type == CONSTANTOP || peer_op_type == CONSTANT) {
  547. if (!AttrUtils::MutableTensor(peer_node->GetOpDesc(), ATTR_NAME_WEIGHTS, ge_tensor)) {
  548. GELOGW("get attr name %s failed.", ATTR_NAME_WEIGHTS.c_str());
  549. return GRAPH_FAILED;
  550. }
  551. return GRAPH_SUCCESS;
  552. } else if (peer_op_type == DATA) {
  553. auto parent_node = NodeUtils::GetParentInput(peer_node);
  554. while ((parent_node != nullptr) && (parent_node->GetType() == DATA)) {
  555. parent_node = NodeUtils::GetParentInput(parent_node);
  556. }
  557. if ((parent_node != nullptr) && ((parent_node->GetType() == CONSTANT) || (parent_node->GetType() == CONSTANTOP))) {
  558. if (!AttrUtils::MutableTensor(parent_node->GetOpDesc(), ATTR_NAME_WEIGHTS, ge_tensor)) {
  559. GELOGW("get attr name %s failed.", ATTR_NAME_WEIGHTS.c_str());
  560. return GRAPH_FAILED;
  561. }
  562. return GRAPH_SUCCESS;
  563. }
  564. }
  565. // Try get from runtime inference context
  566. auto session_id = std::to_string(GetContext().SessionId());
  567. RuntimeInferenceContext *runtime_infer_ctx = nullptr;
  568. if (RuntimeInferenceContext::GetContext(session_id, &runtime_infer_ctx) == GRAPH_SUCCESS) {
  569. GELOGD("To get constant from runtime inference context. session_id = %s", session_id.c_str());
  570. auto ret = runtime_infer_ctx->GetTensor(peer_node->GetOpDesc()->GetId(), out_data_anchor->GetIdx(), ge_tensor);
  571. if (ret == GRAPH_SUCCESS) {
  572. return GRAPH_SUCCESS;
  573. }
  574. }
  575. GELOGW("node[%s]'s input[%s]'s peer node is not const", node.GetName().c_str(), dst_name.c_str());
  576. return GRAPH_FAILED;
  577. }
  578. std::string NodeUtils::GetNodeType(const Node &node) {
  579. if (node.GetType() != FRAMEWORKOP) {
  580. return node.GetType();
  581. }
  582. std::string type;
  583. (void)AttrUtils::GetStr(node.GetOpDesc(), ATTR_NAME_FRAMEWORK_ORIGINAL_TYPE, type);
  584. return type;
  585. }
  586. std::string NodeUtils::GetNodeType(const NodePtr &node) { return node == nullptr ? "" : GetNodeType(*node); }
  587. ComputeGraphPtr NodeUtils::GetSubgraph(const Node &node, uint32_t index) {
  588. auto op_desc = node.GetOpDesc();
  589. if (op_desc == nullptr) {
  590. return nullptr;
  591. }
  592. auto root_graph = GraphUtils::FindRootGraph(node.GetOwnerComputeGraph());
  593. if (root_graph == nullptr) {
  594. return nullptr;
  595. }
  596. return root_graph->GetSubgraph(op_desc->GetSubgraphInstanceName(index));
  597. }
  598. graphStatus NodeUtils::SetSubgraph(Node &node, uint32_t index, const ComputeGraphPtr &subgraph) {
  599. if (subgraph == nullptr) {
  600. GE_LOGE("Failed to set subgraph to node %s index %u, null subgraph", node.GetName().c_str(), index);
  601. return GRAPH_PARAM_INVALID;
  602. }
  603. auto op_desc = node.GetOpDesc();
  604. if (op_desc == nullptr) {
  605. return GRAPH_PARAM_INVALID;
  606. }
  607. auto root_graph = GraphUtils::FindRootGraph(node.GetOwnerComputeGraph());
  608. if (root_graph == nullptr) {
  609. GE_LOGE("Failed to add subgraph to node %s, null root graph", node.GetName().c_str());
  610. return GRAPH_PARAM_INVALID;
  611. }
  612. auto ret = op_desc->SetSubgraphInstanceName(index, subgraph->GetName());
  613. if (ret != GRAPH_SUCCESS) {
  614. GE_LOGE("Failed to set subgraph to node %s index %u", node.GetName().c_str(), index);
  615. return ret;
  616. }
  617. subgraph->SetParentNode(node.shared_from_this());
  618. subgraph->SetParentGraph(node.GetOwnerComputeGraph());
  619. return root_graph->AddSubgraph(subgraph);
  620. }
  621. ///
  622. /// Check if node is input of subgraph
  623. /// @param [in] node
  624. /// @return bool
  625. ///
  626. bool NodeUtils::IsSubgraphInput(const NodePtr &node) {
  627. if ((node == nullptr) || (node->GetOpDesc() == nullptr) ||
  628. (node->GetOwnerComputeGraph()->GetParentNode() == nullptr)) {
  629. return false;
  630. }
  631. auto parent_op_desc = node->GetOwnerComputeGraph()->GetParentNode()->GetOpDesc();
  632. if (parent_op_desc == nullptr) {
  633. return false;
  634. }
  635. // dynamic shape unknown graph false
  636. // dynamic shape known graph with functional subgraph maybe true
  637. if (AttrUtils::HasAttr(parent_op_desc, ATTR_NAME_IS_UNKNOWN_SHAPE)) {
  638. if (node->GetOwnerComputeGraph()->GetParentGraph()->GetGraphUnknownFlag()) {
  639. return false;
  640. } else {
  641. if (node->GetOwnerComputeGraph()->GetParentNode()->GetOwnerComputeGraph()->GetParentNode() == nullptr) {
  642. return false;
  643. }
  644. }
  645. }
  646. return node->GetOpDesc()->HasAttr(ATTR_NAME_PARENT_NODE_INDEX);
  647. }
  648. ///
  649. /// Check if node is output of subgraph
  650. /// @param [in] node
  651. /// @return bool
  652. ///
  653. bool NodeUtils::IsSubgraphOutput(const NodePtr &node) {
  654. if ((node == nullptr) || (node->GetOpDesc() == nullptr) ||
  655. (node->GetOwnerComputeGraph()->GetParentNode() == nullptr) || (node->GetType() != NETOUTPUT)) {
  656. return false;
  657. }
  658. auto parent_op_desc = node->GetOwnerComputeGraph()->GetParentNode()->GetOpDesc();
  659. if (parent_op_desc == nullptr) {
  660. return false;
  661. }
  662. if (AttrUtils::HasAttr(parent_op_desc, ATTR_NAME_IS_UNKNOWN_SHAPE)) {
  663. if (node->GetOwnerComputeGraph()->GetParentGraph()->GetGraphUnknownFlag()) {
  664. return false;
  665. } else {
  666. if (node->GetOwnerComputeGraph()->GetParentNode()->GetOwnerComputeGraph()->GetParentNode() == nullptr) {
  667. return false;
  668. }
  669. }
  670. }
  671. for (GeTensorDesc &tensor : node->GetOpDesc()->GetAllInputsDesc()) {
  672. if (AttrUtils::HasAttr(tensor, ATTR_NAME_PARENT_NODE_INDEX)) {
  673. return true;
  674. }
  675. }
  676. return false;
  677. }
  678. ///
  679. /// @brief Get subgraph original input node.
  680. /// @param [in] node
  681. /// @return Node
  682. ///
  683. NodePtr NodeUtils::GetParentInput(const Node &node) {
  684. uint32_t parent_index = 0;
  685. if (!AttrUtils::GetInt(node.GetOpDesc(), ATTR_NAME_PARENT_NODE_INDEX, parent_index)) {
  686. return nullptr;
  687. }
  688. // Subgraph Data Node, check for constant input.
  689. const ComputeGraphPtr &graph = node.GetOwnerComputeGraph();
  690. GE_CHECK_NOTNULL_EXEC(graph, return nullptr);
  691. const NodePtr &parent_node = graph->GetParentNode();
  692. GE_CHECK_NOTNULL_EXEC(parent_node, return nullptr);
  693. const InDataAnchorPtr &in_anchor = parent_node->GetInDataAnchor(parent_index);
  694. GE_CHECK_NOTNULL_EXEC(in_anchor, return nullptr);
  695. const OutDataAnchorPtr &peer_out_anchor = in_anchor->GetPeerOutAnchor();
  696. GE_CHECK_NOTNULL_EXEC(peer_out_anchor, return nullptr);
  697. return peer_out_anchor->GetOwnerNode();
  698. }
  699. NodePtr NodeUtils::GetParentInput(const NodePtr &node) { return node == nullptr ? node : GetParentInput(*node); }
  700. ///
  701. /// @brief Get is dynamic shape graph from node.
  702. /// @param [in] node
  703. /// @return bool
  704. ///
  705. bool NodeUtils::IsDynamicShape(const Node &node) {
  706. const auto graph = GraphUtils::FindRootGraph(node.GetOwnerComputeGraph());
  707. if (graph == nullptr) {
  708. return false;
  709. }
  710. bool is_dynamic_shape = false;
  711. (void)AttrUtils::GetBool(graph, ATTR_NAME_DYNAMIC_SHAPE_PARTITIONED, is_dynamic_shape);
  712. return is_dynamic_shape;
  713. }
  714. bool NodeUtils::IsDynamicShape(const NodePtr &node) { return node == nullptr ? false : IsDynamicShape(*node); }
  715. ///
  716. /// @brief Check is varying_input for while node
  717. /// @param [in] node: Data node for subgraph
  718. /// @return bool
  719. ///
  720. bool NodeUtils::IsWhileVaryingInput(const ge::NodePtr &node) {
  721. if (node == nullptr) {
  722. return false;
  723. }
  724. if (node->GetType() != DATA) {
  725. return false; // not input_node for subgraph
  726. }
  727. const NodePtr &parent_node = node->GetOwnerComputeGraph()->GetParentNode();
  728. if (parent_node == nullptr) {
  729. return false; // root graph
  730. }
  731. if (kWhileOpTypes.count(parent_node->GetType()) == 0) {
  732. return false; // not input_node for while subgraph
  733. }
  734. uint32_t index_i = 0;
  735. if (!AttrUtils::GetInt(node->GetOpDesc(), ATTR_NAME_PARENT_NODE_INDEX, index_i)) {
  736. GELOGW("Node %s has no attr PARENT_NODE_INDEX.", node->GetName().c_str());
  737. return false;
  738. }
  739. bool varying_flag = true;
  740. for (const auto &item : node->GetOutDataNodesAndAnchors()) {
  741. if (item.first->GetType() != NETOUTPUT) {
  742. continue;
  743. }
  744. OpDescPtr op_desc = item.first->GetOpDesc();
  745. uint32_t index_o = 0;
  746. if ((op_desc == nullptr) ||
  747. !AttrUtils::GetInt(op_desc->GetInputDesc(item.second->GetIdx()), ATTR_NAME_PARENT_NODE_INDEX, index_o)) {
  748. continue; // input for while-cond subgraph
  749. }
  750. if (index_i != index_o) {
  751. continue; // varying input for while-body subgraph
  752. }
  753. varying_flag = false;
  754. break;
  755. }
  756. return varying_flag;
  757. }
  758. ///
  759. /// @brief Get subgraph input is constant.
  760. /// @param [in] node
  761. /// @param [out] string
  762. /// @return bool
  763. ///
  764. bool NodeUtils::GetConstOpType(const NodePtr &node, std::string &type) {
  765. if (node == nullptr) {
  766. return false;
  767. }
  768. if ((node->GetType() == CONSTANT) || (node->GetType() == CONSTANTOP)) {
  769. type = node->GetType();
  770. return true;
  771. }
  772. if (node->GetType() != DATA) {
  773. return false; // not subgraph input node
  774. }
  775. const auto &parent = GetParentInput(node);
  776. return GetConstOpType(parent, type);
  777. }
  778. ///
  779. /// @brief Remove node-related subgraphs, including subgraphs of nodes in the subgraph.
  780. /// @param [in] node
  781. /// @return return GRAPH_SUCCESS if remove successfully, other for failed.
  782. ///
  783. Status NodeUtils::RemoveSubgraphsOnNode(const NodePtr &node) {
  784. GE_CHECK_NOTNULL(node);
  785. auto op_desc = node->GetOpDesc();
  786. GE_CHECK_NOTNULL(op_desc);
  787. auto subgraph_names = op_desc->GetSubgraphInstanceNames();
  788. if (subgraph_names.empty()) {
  789. return GRAPH_SUCCESS;
  790. } else {
  791. auto owner_graph = node->GetOwnerComputeGraph();
  792. GE_CHECK_NOTNULL(owner_graph);
  793. auto root_graph = GraphUtils::FindRootGraph(owner_graph);
  794. GE_CHECK_NOTNULL(root_graph);
  795. std::unordered_set<std::string> subgraph_to_remove;
  796. for (auto &subgraph_name : subgraph_names) {
  797. std::deque<std::string> queue;
  798. queue.push_back(subgraph_name);
  799. subgraph_to_remove.insert(subgraph_name);
  800. op_desc->RemoveSubgraphInstanceName(subgraph_name);
  801. while (!queue.empty()) {
  802. auto graph_name = queue.front();
  803. queue.pop_front();
  804. auto subgraph = root_graph->GetSubgraph(graph_name);
  805. GE_CHECK_NOTNULL(subgraph);
  806. for (const auto &sub_node : subgraph->GetDirectNode()) {
  807. auto sub_op_desc = sub_node->GetOpDesc();
  808. GE_CHECK_NOTNULL(sub_op_desc);
  809. auto sub_names = sub_op_desc->GetSubgraphInstanceNames();
  810. // Subgraph and all nodes in it will be removed later,
  811. // no need to remove 'SubgraphInstanceName' in op desc here.
  812. for (auto &name : sub_names) {
  813. if (subgraph_to_remove.insert(name).second) {
  814. queue.push_back(name);
  815. }
  816. }
  817. }
  818. }
  819. }
  820. // Remove subgraph from root_graph
  821. for (const auto &name : subgraph_to_remove) {
  822. GELOGI("Remove subgraph:%s.", name.c_str());
  823. root_graph->RemoveSubgraph(name);
  824. }
  825. }
  826. return GRAPH_SUCCESS;
  827. }
  828. ///
  829. /// @brief Get subgraph input data node by index.
  830. /// @param [in] node
  831. /// @return Node
  832. ///
  833. vector<NodePtr> NodeUtils::GetSubgraphDataNodesByIndex(const Node &node, int index) {
  834. vector<NodePtr> in_data_node_vec;
  835. auto op_desc = node.GetOpDesc();
  836. GE_CHECK_NOTNULL_EXEC(op_desc, return in_data_node_vec);
  837. auto subgraph_names = op_desc->GetSubgraphInstanceNames();
  838. if (subgraph_names.empty()) {
  839. GELOGW("Node %s is single node without sub graph.", node.GetName().c_str());
  840. return in_data_node_vec;
  841. }
  842. auto compute_graph = node.GetOwnerComputeGraph();
  843. for (const std::string &instance_name : subgraph_names) {
  844. auto subgraph = compute_graph->GetSubgraph(instance_name);
  845. for (const auto &node_in_subgraph : subgraph->GetDirectNode()) {
  846. int parent_index = -1;
  847. if (NodeUtils::IsSubgraphInput(node_in_subgraph)) {
  848. (void)AttrUtils::GetInt(node_in_subgraph->GetOpDesc(), ATTR_NAME_PARENT_NODE_INDEX, parent_index);
  849. if (parent_index == index) {
  850. in_data_node_vec.emplace_back(node_in_subgraph);
  851. }
  852. }
  853. }
  854. }
  855. return in_data_node_vec;
  856. }
  857. ///
  858. /// @brief Get subgraph input data node by index.
  859. /// @param [in] node
  860. /// @return Node
  861. ///
  862. vector<NodePtr> NodeUtils::GetSubgraphOutputNodes(const Node &node) {
  863. vector<NodePtr> out_data_node_vec;
  864. auto op_desc = node.GetOpDesc();
  865. GE_CHECK_NOTNULL_EXEC(op_desc, return out_data_node_vec);
  866. auto subgraph_names = op_desc->GetSubgraphInstanceNames();
  867. if (subgraph_names.empty()) {
  868. GELOGI("Node %s is single node without sub graph.", node.GetName().c_str());
  869. return out_data_node_vec;
  870. }
  871. auto compute_graph = node.GetOwnerComputeGraph();
  872. for (const std::string &instance_name : subgraph_names) {
  873. auto subgraph = compute_graph->GetSubgraph(instance_name);
  874. for (const auto &node_in_subgraph : subgraph->GetDirectNode()) {
  875. if (NodeUtils::IsSubgraphOutput(node_in_subgraph)) {
  876. out_data_node_vec.emplace_back(node_in_subgraph);
  877. }
  878. }
  879. }
  880. return out_data_node_vec;
  881. }
  882. NodePtr NodeUtils::GetInDataNodeByIndex(const Node &node, const int index) {
  883. if (node.GetInDataAnchor(index) == nullptr) {
  884. return nullptr;
  885. }
  886. if (node.GetInDataAnchor(index)->GetPeerOutAnchor() == nullptr) {
  887. return nullptr;
  888. }
  889. return node.GetInDataAnchor(index)->GetPeerOutAnchor()->GetOwnerNode();
  890. }
  891. vector<pair<InDataAnchorPtr, NodePtr>> NodeUtils::GetOutDataNodesWithAnchorByIndex(const Node &node, const int index) {
  892. vector<pair<InDataAnchorPtr, NodePtr>> out_data_nodes;
  893. auto out_data_anchor = node.GetOutDataAnchor(index);
  894. if (out_data_anchor == nullptr) {
  895. return out_data_nodes;
  896. }
  897. for (const auto peer_in_anchor : out_data_anchor->GetPeerInDataAnchors()) {
  898. if (peer_in_anchor == nullptr) {
  899. continue;
  900. }
  901. if (peer_in_anchor->GetOwnerNode() == nullptr) {
  902. continue;
  903. }
  904. out_data_nodes.emplace_back(std::make_pair(peer_in_anchor, peer_in_anchor->GetOwnerNode()));
  905. }
  906. return out_data_nodes;
  907. }
  908. ConstNodePtr NodeUtils::GetNodeFromOperator(const Operator &oprt) { return oprt.GetNode(); }
  909. } // namespace ge

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