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.

stream_allocator_unittest.cc 7.9 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. /**
  2. * Copyright 2021 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 <string>
  17. #include <vector>
  18. #include <gtest/gtest.h>
  19. #define protected public
  20. #define private public
  21. #include "graph/build/stream_allocator.h"
  22. #undef protected
  23. #undef private
  24. #include "graph/debug/ge_attr_define.h"
  25. #include "graph/utils/graph_utils.h"
  26. namespace ge {
  27. class UtestStreamAllocator : public testing::Test {
  28. protected:
  29. void SetUp() {}
  30. void TearDown() {}
  31. public:
  32. ///
  33. /// A
  34. /// / \.
  35. /// B C
  36. /// | |
  37. /// D 400
  38. /// | |
  39. /// | E
  40. /// \ /
  41. /// F
  42. ///
  43. void make_graph_active(const ComputeGraphPtr &graph) {
  44. const auto &a_desc = std::make_shared<OpDesc>("A", DATA);
  45. a_desc->AddInputDesc(GeTensorDesc());
  46. a_desc->AddOutputDesc(GeTensorDesc());
  47. a_desc->SetStreamId(0);
  48. const auto &a_node = graph->AddNode(a_desc);
  49. const auto &b_desc = std::make_shared<OpDesc>("B", "testa");
  50. b_desc->AddInputDesc(GeTensorDesc());
  51. b_desc->AddOutputDesc(GeTensorDesc());
  52. b_desc->SetStreamId(1);
  53. AttrUtils::SetListStr(b_desc, ATTR_NAME_ACTIVE_LABEL_LIST, {"1"});
  54. const auto &b_node = graph->AddNode(b_desc);
  55. const auto &c_desc = std::make_shared<OpDesc>("C", "testa");
  56. c_desc->AddInputDesc(GeTensorDesc());
  57. c_desc->AddOutputDesc(GeTensorDesc());
  58. c_desc->SetStreamId(2);
  59. AttrUtils::SetStr(c_desc, ATTR_NAME_STREAM_LABEL, "1");
  60. const auto &c_node = graph->AddNode(c_desc);
  61. const auto &d_desc = std::make_shared<OpDesc>("D", "testa");
  62. d_desc->AddInputDesc(GeTensorDesc());
  63. d_desc->AddOutputDesc(GeTensorDesc());
  64. d_desc->SetStreamId(1);
  65. const auto &d_node = graph->AddNode(d_desc);
  66. const auto &e_desc = std::make_shared<OpDesc>("E", "testa");
  67. e_desc->AddInputDesc(GeTensorDesc());
  68. e_desc->AddOutputDesc(GeTensorDesc());
  69. e_desc->SetStreamId(2);
  70. const auto &e_node = graph->AddNode(e_desc);
  71. const auto &f_desc = std::make_shared<OpDesc>("F", "testa");
  72. f_desc->AddInputDesc(GeTensorDesc());
  73. f_desc->AddInputDesc(GeTensorDesc());
  74. f_desc->AddOutputDesc(GeTensorDesc());
  75. f_desc->SetStreamId(2);
  76. const auto &f_node = graph->AddNode(f_desc);
  77. std::vector<NodePtr> node_list(400);
  78. for (int i = 0; i < 400; i++) {
  79. const auto &op_desc = std::make_shared<OpDesc>("X", DATA);
  80. op_desc->AddInputDesc(GeTensorDesc());
  81. op_desc->AddOutputDesc(GeTensorDesc());
  82. op_desc->SetStreamId(2);
  83. node_list[i] = graph->AddNode(op_desc);
  84. }
  85. GraphUtils::AddEdge(a_node->GetOutDataAnchor(0), b_node->GetInDataAnchor(0));
  86. GraphUtils::AddEdge(a_node->GetOutDataAnchor(0), c_node->GetInDataAnchor(0));
  87. GraphUtils::AddEdge(b_node->GetOutDataAnchor(0), d_node->GetInDataAnchor(0));
  88. GraphUtils::AddEdge(d_node->GetOutDataAnchor(0), f_node->GetInDataAnchor(0));
  89. GraphUtils::AddEdge(c_node->GetOutDataAnchor(0), node_list[0]->GetInDataAnchor(0));
  90. for (uint32_t i = 0; i < 399; i++) {
  91. GraphUtils::AddEdge(node_list[i]->GetOutDataAnchor(0), node_list[i + 1]->GetInDataAnchor(0));
  92. }
  93. GraphUtils::AddEdge(node_list[399]->GetOutDataAnchor(0), e_node->GetInDataAnchor(0));
  94. GraphUtils::AddEdge(e_node->GetOutDataAnchor(0), f_node->GetInDataAnchor(1));
  95. }
  96. };
  97. TEST_F(UtestStreamAllocator, test_split_streams_active) {
  98. const auto &graph = std::make_shared<ComputeGraph>("test_split_streams_active_graph");
  99. EXPECT_NE(graph, nullptr);
  100. make_graph_active(graph);
  101. StreamAllocator allocator(graph, Graph2SubGraphInfoList());
  102. allocator.stream_num_ = 3;
  103. EXPECT_EQ(allocator.SetActiveStreamsByLabel(), SUCCESS);
  104. std::vector<std::set<int64_t>> split_stream(3);
  105. EXPECT_EQ(allocator.SplitStreams(split_stream), SUCCESS);
  106. EXPECT_EQ(allocator.UpdateActiveStreams(split_stream), SUCCESS);
  107. EXPECT_EQ(allocator.SetActiveStreamsForLoop(), SUCCESS);
  108. EXPECT_EQ(allocator.specific_activated_streams_.count(3), 1);
  109. const auto &node_b = graph->FindNode("B");
  110. EXPECT_NE(node_b, nullptr);
  111. std::vector<uint32_t> active_stream_list;
  112. EXPECT_TRUE(AttrUtils::GetListInt(node_b->GetOpDesc(), ATTR_NAME_ACTIVE_STREAM_LIST, active_stream_list));
  113. EXPECT_EQ(active_stream_list.size(), 2);
  114. const auto &node_e = graph->FindNode("E");
  115. EXPECT_NE(node_e, nullptr);
  116. EXPECT_EQ(active_stream_list[0], node_e->GetOpDesc()->GetStreamId());
  117. EXPECT_EQ(active_stream_list[1], 3);
  118. }
  119. TEST_F(UtestStreamAllocator, test_update_active_streams_for_subgraph) {
  120. const auto &root_graph = std::make_shared<ComputeGraph>("test_update_active_streams_for_subgraph_root_graph");
  121. EXPECT_NE(root_graph, nullptr);
  122. root_graph->SetGraphUnknownFlag(false);
  123. const auto &sub_graph1 = std::make_shared<ComputeGraph>("test_update_active_streams_for_subgraph_sub_graph1");
  124. EXPECT_NE(sub_graph1, nullptr);
  125. root_graph->AddSubGraph(sub_graph1);
  126. const auto &sub_graph2 = std::make_shared<ComputeGraph>("test_update_active_streams_for_subgraph_sub_graph2");
  127. EXPECT_NE(sub_graph2, nullptr);
  128. root_graph->AddSubGraph(sub_graph2);
  129. const auto &case_desc = std::make_shared<OpDesc>("case", CASE);
  130. EXPECT_NE(case_desc, nullptr);
  131. EXPECT_EQ(case_desc->AddInputDesc(GeTensorDesc()), GRAPH_SUCCESS);
  132. EXPECT_EQ(case_desc->AddOutputDesc(GeTensorDesc()), GRAPH_SUCCESS);
  133. case_desc->AddSubgraphName("branch1");
  134. case_desc->SetSubgraphInstanceName(0, "test_update_active_streams_for_subgraph_sub_graph1");
  135. case_desc->AddSubgraphName("branch2");
  136. case_desc->SetSubgraphInstanceName(1, "test_update_active_streams_for_subgraph_sub_graph2");
  137. const auto &case_node = root_graph->AddNode(case_desc);
  138. EXPECT_NE(case_node, nullptr);
  139. sub_graph1->SetParentNode(case_node);
  140. sub_graph2->SetParentNode(case_node);
  141. const auto &active_desc1 = std::make_shared<OpDesc>("active1", STREAMACTIVE);
  142. EXPECT_NE(active_desc1, nullptr);
  143. EXPECT_TRUE(AttrUtils::SetListInt(active_desc1, ATTR_NAME_ACTIVE_STREAM_LIST, {0}));
  144. const auto &active_node1 = sub_graph1->AddNode(active_desc1);
  145. EXPECT_NE(active_node1, nullptr);
  146. const auto &active_desc2 = std::make_shared<OpDesc>("active2", STREAMACTIVE);
  147. EXPECT_NE(active_desc2, nullptr);
  148. EXPECT_TRUE(AttrUtils::SetListInt(active_desc2, ATTR_NAME_ACTIVE_STREAM_LIST, {1}));
  149. const auto &active_node2 = sub_graph2->AddNode(active_desc2);
  150. EXPECT_NE(active_node2, nullptr);
  151. StreamAllocator allocator(root_graph, Graph2SubGraphInfoList());
  152. allocator.node_split_stream_map_[active_node1] = 2;
  153. allocator.node_split_stream_map_[active_node2] = 3;
  154. allocator.split_ori_stream_map_[2] = 0;
  155. allocator.subgraph_first_active_node_map_[sub_graph1] = active_node1;
  156. allocator.subgraph_first_active_node_map_[sub_graph2] = active_node2;
  157. EXPECT_EQ(allocator.UpdateActiveStreamsForSubgraphs(), SUCCESS);
  158. std::vector<uint32_t> active_stream_list1;
  159. EXPECT_TRUE(AttrUtils::GetListInt(active_node1->GetOpDesc(), ATTR_NAME_ACTIVE_STREAM_LIST, active_stream_list1));
  160. EXPECT_EQ(active_stream_list1.size(), 1);
  161. EXPECT_EQ(active_stream_list1[0], 0);
  162. std::vector<uint32_t> active_stream_list2;
  163. EXPECT_TRUE(AttrUtils::GetListInt(active_node2->GetOpDesc(), ATTR_NAME_ACTIVE_STREAM_LIST, active_stream_list2));
  164. EXPECT_EQ(active_stream_list2.size(), 2);
  165. EXPECT_EQ(active_stream_list2[0], 1);
  166. EXPECT_EQ(active_stream_list2[1], 3);
  167. EXPECT_EQ(allocator.specific_activated_streams_.size(), 1);
  168. EXPECT_EQ(allocator.specific_activated_streams_.count(3), 1);
  169. }
  170. }

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