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_item.cc 7.2 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  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 "node_item.h"
  17. #include <sstream>
  18. #include "common/debug/log.h"
  19. #include "graph/common/omg_util.h"
  20. #include "graph/compute_graph.h"
  21. #include "graph/debug/ge_attr_define.h"
  22. #include "graph/utils/node_utils.h"
  23. #include "hybrid/node_executor/node_executor.h"
  24. namespace ge {
  25. namespace hybrid {
  26. namespace {
  27. const char *const kAttrNameOriginalFusionGraph = "_original_fusion_graph";
  28. const char *const kNodeTypeRetVal = "_RetVal";
  29. std::set<std::string> kControlOpTypes{IF, STATELESSIF, CASE, WHILE, STATELESSWHILE};
  30. Status ParseInputMapping(Node &node, OpDesc &op_desc, FusedSubgraph &fused_subgraph) {
  31. uint32_t parent_index = 0;
  32. if (!AttrUtils::GetInt(op_desc, ATTR_NAME_PARENT_NODE_INDEX, parent_index)) {
  33. GELOGE(FAILED, "[%s] Failed to get attr [%s]", op_desc.GetName().c_str(), ATTR_NAME_PARENT_NODE_INDEX.c_str());
  34. return FAILED;
  35. }
  36. for (auto &node_and_anchor : node.GetOutDataNodesAndAnchors()) {
  37. auto dst_op_desc = node_and_anchor.first->GetOpDesc();
  38. GE_CHECK_NOTNULL(dst_op_desc);
  39. auto in_idx = node_and_anchor.second->GetIdx();
  40. auto tensor_desc = dst_op_desc->MutableInputDesc(in_idx);
  41. fused_subgraph.input_mapping[parent_index].emplace_back(tensor_desc);
  42. GELOGD("Input[%u] mapped to [%s:%u]", parent_index, dst_op_desc->GetName().c_str(), in_idx);
  43. }
  44. return SUCCESS;
  45. }
  46. Status ParseOutputMapping(OpDescPtr op_desc, FusedSubgraph &fused_subgraph) {
  47. uint32_t parent_index = 0;
  48. if (!AttrUtils::GetInt(op_desc, ATTR_NAME_PARENT_NODE_INDEX, parent_index)) {
  49. GELOGE(FAILED, "[%s] Failed to get attr [%s]", op_desc->GetName().c_str(), ATTR_NAME_PARENT_NODE_INDEX.c_str());
  50. return FAILED;
  51. }
  52. fused_subgraph.output_mapping.emplace(parent_index, op_desc);
  53. return SUCCESS;
  54. }
  55. Status ParseFusedSubgraph(NodeItem &node_item) {
  56. if (!node_item.op_desc->HasAttr(kAttrNameOriginalFusionGraph)) {
  57. return SUCCESS;
  58. }
  59. GELOGI("[%s] Start to parse fused subgraph.", node_item.node_name.c_str());
  60. auto fused_subgraph = std::unique_ptr<FusedSubgraph>(new (std::nothrow) FusedSubgraph());
  61. GE_CHECK_NOTNULL(fused_subgraph);
  62. ComputeGraphPtr fused_graph;
  63. (void)AttrUtils::GetGraph(*node_item.op_desc, kAttrNameOriginalFusionGraph, fused_graph);
  64. GE_CHECK_NOTNULL(fused_graph);
  65. fused_graph->SetGraphUnknownFlag(true);
  66. fused_subgraph->graph = fused_graph;
  67. GE_CHK_GRAPH_STATUS_RET(fused_graph->TopologicalSorting());
  68. for (auto &node : fused_graph->GetAllNodes()) {
  69. GE_CHECK_NOTNULL(node);
  70. auto op_desc = node->GetOpDesc();
  71. GE_CHECK_NOTNULL(op_desc);
  72. std::string node_type;
  73. GE_CHK_STATUS_RET(GetOriginalType(node, node_type));
  74. if (node_type == DATA) {
  75. GE_CHK_GRAPH_STATUS_RET(ParseInputMapping(*node, *op_desc, *fused_subgraph));
  76. } else if (node_type == kNodeTypeRetVal) {
  77. GE_CHK_GRAPH_STATUS_RET(ParseOutputMapping(op_desc, *fused_subgraph));
  78. } else {
  79. fused_subgraph->nodes.emplace_back(node);
  80. }
  81. }
  82. node_item.fused_subgraph = std::move(fused_subgraph);
  83. GELOGI("[%s] Done parsing fused subgraph successfully.", node_item.NodeName().c_str());
  84. return SUCCESS;
  85. }
  86. } // namespace
  87. bool IsControlOp(const std::string &op_type) { return kControlOpTypes.count(op_type) > 0; }
  88. NodeItem::NodeItem(NodePtr node) : node(std::move(node)) {
  89. this->op_desc = this->node->GetOpDesc().get();
  90. this->node_id = this->op_desc->GetId();
  91. this->num_inputs = this->op_desc->GetInputsSize();
  92. this->num_outputs = this->op_desc->GetOutputsSize();
  93. this->node_name = this->node->GetName();
  94. this->node_type = this->node->GetType();
  95. }
  96. Status NodeItem::Init() {
  97. int32_t unknown_shape_type_val = 0;
  98. (void)AttrUtils::GetInt(op_desc, ::ge::ATTR_NAME_UNKNOWN_SHAPE_TYPE, unknown_shape_type_val);
  99. shape_inference_type = static_cast<UnknowShapeOpType>(unknown_shape_type_val);
  100. (void)AttrUtils::GetBool(op_desc, ATTR_NAME_FORCE_UNKNOWN_SHAPE, is_dynamic);
  101. GELOGD("node name = %s, is_dynamic = %d.", this->node_name.c_str(), is_dynamic);
  102. if (!is_dynamic) {
  103. GE_CHK_STATUS_RET(NodeUtils::GetNodeUnknownShapeStatus(*node, is_dynamic), "[%s] Failed to get shape status.",
  104. node->GetName().c_str());
  105. }
  106. GE_CHK_STATUS_RET(ParseFusedSubgraph(*this), "[%s] Failed to parse fused subgraph", node_name.c_str());
  107. if (is_dynamic) {
  108. for (int i = 0; i < num_inputs; ++i) {
  109. const auto &input_desc = op_desc->MutableInputDesc(i);
  110. GE_CHECK_NOTNULL(input_desc);
  111. if (input_desc->MutableShape().IsUnknownShape()) {
  112. is_input_shape_static.push_back(false);
  113. } else {
  114. num_static_input_shapes++;
  115. is_input_shape_static.push_back(true);
  116. GELOGD("[%s] The shape of input[%d] is static. shape = [%s]", NodeName().c_str(), i,
  117. input_desc->MutableShape().ToString().c_str());
  118. }
  119. }
  120. for (int i = 0; i < num_outputs; ++i) {
  121. const auto &output_desc = op_desc->MutableOutputDesc(i);
  122. GE_CHECK_NOTNULL(output_desc);
  123. if (output_desc->MutableShape().IsUnknownShape()) {
  124. is_output_shape_static = false;
  125. break;
  126. }
  127. }
  128. }
  129. return SUCCESS;
  130. }
  131. bool NodeItem::IsControlOp() const { return ge::hybrid::IsControlOp(op_desc->GetType()); }
  132. std::string NodeItem::DebugString() const {
  133. std::stringstream ss;
  134. ss << "Node: ";
  135. ss << "id = " << node_id;
  136. ss << ", name = [" << node->GetName();
  137. ss << "], type = " << node->GetType();
  138. ss << ", is_dynamic = " << (is_dynamic ? "True" : "False");
  139. ss << ", is_output_static = " << (is_output_shape_static ? "True" : "False");
  140. ss << ", unknown_shape_op_type = " << shape_inference_type;
  141. ss << ", input_start = " << input_start;
  142. ss << ", num_inputs = " << num_inputs;
  143. ss << ", output_start = " << output_start;
  144. ss << ", num_outputs = " << num_outputs;
  145. ss << ", dependent_nodes = [";
  146. for (const auto &dep_node : dependents_for_shape_inference) {
  147. ss << dep_node->GetName() << ", ";
  148. }
  149. ss << "]";
  150. int index = 0;
  151. for (auto &items : outputs) {
  152. ss << ", output[" << index++ << "]: ";
  153. for (auto &item : items) {
  154. ss << "(" << item.second->NodeName() << ":" << item.first << "), ";
  155. }
  156. }
  157. return ss.str();
  158. }
  159. void NodeItem::SetToDynamic() {
  160. num_static_input_shapes = 0;
  161. is_dynamic = true;
  162. for (size_t i = 0; i < is_input_shape_static.size(); ++i) {
  163. is_input_shape_static[i] = false;
  164. }
  165. if (kernel_task != nullptr && !kernel_task->IsSupportDynamicShape()) {
  166. GELOGD("[%s] Dynamic shape is not supported, clear node task.", node_name.c_str());
  167. kernel_task = nullptr;
  168. }
  169. }
  170. } // namespace hybrid
  171. } // namespace ge

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