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.

new_op_test_utils.h 18 kB

5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  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. #ifndef OME_REBUILD_OME_OP_TEST_UTILS_H
  17. #define OME_REBUILD_OME_OP_TEST_UTILS_H
  18. #include <gtest/gtest.h>
  19. #include <memory>
  20. #include <utility>
  21. #include "common/fmk_types.h"
  22. #include "common/helper/model_helper.h"
  23. #include "common/op/attr_value_util.h"
  24. #include "common/properties_manager.h"
  25. #include "common/types.h"
  26. #include "executor/ge_executor.h"
  27. #include "graph/buffer.h"
  28. #include "graph/debug/ge_attr_define.h"
  29. #include "graph/ge_attr_value.h"
  30. #include "graph/model_serialize.h"
  31. #include "graph/utils/graph_utils.h"
  32. #include "graph/utils/op_desc_utils.h"
  33. #include "graph/utils/tensor_utils.h"
  34. #include "proto/ge_ir.pb.h"
  35. #define protected public
  36. #define private public
  37. #include "graph/compute_graph.h"
  38. #include "graph/debug/ge_attr_define.h"
  39. #include "graph/load/new_model_manager/davinci_model.h"
  40. #include "graph/node.h"
  41. #include "graph/op_desc.h"
  42. #include "graph/utils/attr_utils.h"
  43. #include "graph/utils/graph_utils.h"
  44. #include "graph/utils/op_desc_utils.h"
  45. #include "graph/utils/tensor_utils.h"
  46. #undef protected
  47. #undef private
  48. using namespace ge;
  49. class GlobalModelData {
  50. public:
  51. GlobalModelData() {}
  52. ~GlobalModelData() {
  53. if (data_.model_data != nullptr) {
  54. delete[](uint8_t *) data_.model_data;
  55. data_.model_data = nullptr;
  56. }
  57. }
  58. ge::ModelData data_;
  59. };
  60. static GlobalModelData g_model_data;
  61. class OmeTestOpUtils {
  62. public:
  63. static void InitModel(std::shared_ptr<ge::DavinciModel> davinciModel) { InitModel(*davinciModel); }
  64. static ge::NodePtr GenNodeFromOpDesc(ge::OpDescPtr op_desc) {
  65. if (!op_desc) {
  66. return nullptr;
  67. }
  68. auto g = std::make_shared<ge::ComputeGraph>("g");
  69. return g->AddNode(std::move(op_desc));
  70. }
  71. static void AddInputOutputToTaskModel(std::shared_ptr<ge::Model> model,
  72. std::shared_ptr<domi::ModelTaskDef> model_task_def) {
  73. uint32_t stream_num111 = model_task_def->stream_num();
  74. uint32_t weights_num = model_task_def->weight_size();
  75. uint32_t mem_num = model_task_def->memory_size();
  76. int64_t memory_size = 0;
  77. int64_t weight_size = 0;
  78. (void)ge::AttrUtils::GetInt(model.get(), ATTR_MODEL_MEMORY_SIZE, memory_size);
  79. (void)ge::AttrUtils::GetInt(model.get(), ATTR_MODEL_WEIGHT_SIZE, weight_size);
  80. // Save memory_size/weight_size/stream_num/event_num to proto
  81. model_task_def->set_memory_size(memory_size);
  82. model_task_def->set_weight_size(weight_size);
  83. int64_t stream_num = 0;
  84. (void)ge::AttrUtils::GetInt(model.get(), ATTR_MODEL_STREAM_NUM, stream_num);
  85. model_task_def->set_stream_num(stream_num);
  86. ge::ComputeGraphPtr graph = ge::GraphUtils::GetComputeGraph(model->GetGraph());
  87. vector<ConstOpDescPtr> op_desc_ptrs;
  88. for (const auto &node_ptr : graph->GetAllNodes()) {
  89. if (node_ptr->GetType() == DATA_TYPE || node_ptr->GetType() == ANN_DATA_TYPE) {
  90. op_desc_ptrs.push_back(node_ptr->GetOpDesc());
  91. continue;
  92. }
  93. for (auto tensor_desc : node_ptr->GetOpDesc()->GetAllOutputsDescPtr()) {
  94. bool is_output = false;
  95. ge::TensorUtils::GetOutputTensor(*tensor_desc, is_output);
  96. if (is_output) {
  97. // output Op and add to array
  98. op_desc_ptrs.push_back(node_ptr->GetOpDesc());
  99. break;
  100. }
  101. }
  102. }
  103. // save multi OpDescPtr to attr
  104. ge::ModelSerialize model_serialize;
  105. for (auto op_desc_ptr : op_desc_ptrs) {
  106. ge::Buffer buffer = model_serialize.SerializeOpDesc(op_desc_ptr);
  107. model_task_def->add_op(string(reinterpret_cast<const char *>(buffer.GetData()), buffer.GetSize()));
  108. }
  109. int64_t run_mode = -1;
  110. for (auto node_ptr : graph->GetAllNodes()) {
  111. // TE CUSTOM op need to init
  112. if (ge::AttrUtils::GetInt(node_ptr->GetOpDesc(), ATTR_NAME_IMPLY_TYPE, run_mode) &&
  113. run_mode != (uint32_t)domi::ImplyType::BUILDIN && run_mode != (uint32_t)domi::ImplyType::INVALID) {
  114. (*(model_task_def->mutable_attr()))["contain_custom"] = "1";
  115. break;
  116. }
  117. }
  118. }
  119. static Status TransModelToGeModel(const ModelPtr &model, GeModelPtr &ge_model) {
  120. if (model == nullptr) {
  121. GELOGE(FAILED, "Model is null");
  122. return FAILED;
  123. }
  124. ge_model = ge::MakeShared<ge::GeModel>();
  125. GE_CHECK_NOTNULL(ge_model);
  126. ge_model->SetGraph(model->GetGraph());
  127. ge_model->SetName(model->GetName());
  128. ge_model->SetVersion(model->GetVersion());
  129. ge_model->SetPlatformVersion(model->GetPlatformVersion());
  130. ge_model->SetAttr(model->MutableAttrMap());
  131. auto compute_graph = ge::GraphUtils::GetComputeGraph(model->GetGraph());
  132. ge::Buffer weight;
  133. (void)ge::AttrUtils::GetZeroCopyBytes(compute_graph, ge::ATTR_NAME_WEIGHTS_DATA, weight);
  134. ge_model->SetWeight(weight);
  135. if (model->HasAttr(MODEL_ATTR_TASKS)) {
  136. ge::Buffer task_buffer;
  137. GE_CHK_BOOL_RET_STATUS(ge::AttrUtils::GetZeroCopyBytes(model, MODEL_ATTR_TASKS, task_buffer), FAILED,
  138. "Get bytes failed.");
  139. std::shared_ptr<ModelTaskDef> task = ge::MakeShared<ModelTaskDef>();
  140. GE_CHECK_NOTNULL(task);
  141. GE_IF_BOOL_EXEC(task_buffer.GetData() == nullptr, GELOGE(FAILED, "Get data fail"); return FAILED);
  142. GE_IF_BOOL_EXEC(task_buffer.GetSize() == 0, GELOGE(FAILED, "Get size fail"); return FAILED);
  143. GE_CHK_BOOL_EXEC(ReadProtoFromArray(task_buffer.GetData(), static_cast<int>(task_buffer.GetSize()), task.get()),
  144. return INTERNAL_ERROR, "ReadProtoFromArray failed.");
  145. ge_model->SetModelTaskDef(task);
  146. }
  147. TBEKernelStore kernel_store;
  148. if (compute_graph != nullptr && compute_graph->GetDirectNodesSize() != 0) {
  149. for (const ge::NodePtr &n : compute_graph->GetDirectNode()) {
  150. auto node_op_desc = n->GetOpDesc();
  151. GE_IF_BOOL_EXEC(node_op_desc == nullptr, continue);
  152. TBEKernelPtr tbe_kernel = node_op_desc->TryGetExtAttr(ge::OP_EXTATTR_NAME_TBE_KERNEL, TBEKernelPtr());
  153. GE_IF_BOOL_EXEC(tbe_kernel == nullptr, continue);
  154. kernel_store.AddTBEKernel(tbe_kernel);
  155. GELOGI("Add tbe kernel bin %s", tbe_kernel->GetName().c_str());
  156. }
  157. }
  158. if (!kernel_store.Build()) {
  159. GELOGE(FAILED, "TBE Kernels store build failed!");
  160. return FAILED;
  161. }
  162. ge_model->SetTBEKernelStore(kernel_store);
  163. return SUCCESS;
  164. }
  165. static void LoadStandardModelDataLocal(ge::ModelData &data) {
  166. static const std::string STANDARD_MODEL_DATA_PATH =
  167. "llt/framework/domi/ut/ome/test/data/standard_partition_model.txt";
  168. ge::proto::ModelDef model_def;
  169. ReadProtoFromText(STANDARD_MODEL_DATA_PATH.c_str(), &model_def);
  170. data.model_len = model_def.ByteSizeLong();
  171. data.model_data = new uint8_t[data.model_len];
  172. model_def.SerializePartialToArray(data.model_data, data.model_len);
  173. }
  174. static void InitModel(ge::DavinciModel &davinciModel) {
  175. ge::ModelData data;
  176. LoadStandardModelDataLocal(data);
  177. std::shared_ptr<ge::Model> model_ = std::make_shared<ge::Model>();
  178. ge::Model::Load((uint8_t *)data.model_data, data.model_len, *model_);
  179. GeModelPtr ge_model;
  180. TransModelToGeModel(model_, ge_model);
  181. davinciModel.Assign(ge_model);
  182. if (data.model_data != nullptr) {
  183. delete[](uint8_t *) data.model_data;
  184. }
  185. }
  186. static void InitEmptyModel(ge::DavinciModel &davinciModel) {
  187. auto model = std::make_shared<ge::Model>();
  188. ge::AttrUtils::SetInt(model, ATTR_MODEL_MEMORY_SIZE, 81000000);
  189. ge::AttrUtils::SetInt(model, ATTR_MODEL_WEIGHT_SIZE, 4100000);
  190. ge::AttrUtils::SetInt(model, ATTR_MODEL_STREAM_NUM, 1);
  191. ge::AttrUtils::SetInt(model, ATTR_MODEL_EVENT_NUM, 1);
  192. ge::AttrUtils::SetInt(model, MODEL_ATTR_TASK_GEN_BASE_ADDR, 0x123);
  193. ge::AttrUtils::SetInt(model, MODEL_ATTR_TASK_GEN_WEIGHT_ADDR, 0x456);
  194. ge::AttrUtils::SetInt(model, ATTR_MODEL_BATCH_NUM, 1);
  195. // ge::AttrUtils::SetStr(model, ATTR_MODEL_TARGET_TYPE, "MINI"); // domi::MINI
  196. auto compute_graph = std::make_shared<ge::ComputeGraph>("graph");
  197. ge::GeAttrValue::BYTES buffer(4100000, 0);
  198. ge::AttrUtils::SetBytes(compute_graph, "weights_data", buffer);
  199. auto graph = ge::GraphUtils::CreateGraphFromComputeGraph(compute_graph);
  200. model->SetGraph(graph);
  201. GeModelPtr ge_model;
  202. TransModelToGeModel(model, ge_model);
  203. davinciModel.Assign(ge_model);
  204. }
  205. static void InitModelWithoutMem(ge::DavinciModel &davinciModel) { InitModel(davinciModel); }
  206. static Status ModelLoadStub(const uint8_t *data, size_t len, ge::Model &model) {
  207. auto compute_graph = std::make_shared<ge::ComputeGraph>("graph");
  208. auto graph = ge::GraphUtils::CreateGraphFromComputeGraph(compute_graph);
  209. model.SetGraph(graph);
  210. return SUCCESS;
  211. }
  212. static void InitDefaultTensorDesc(ge::GeTensorDesc &tensor_desc) {}
  213. static void AddInputDesc(ge::OpDescPtr op_desc, vector<int64_t> shape, ge::Format format, ge::DataType dataType,
  214. int64_t dataSize = 0) {
  215. ge::GeTensorDesc tensor_desc(ge::GeShape(shape), format, dataType);
  216. InitDefaultTensorDesc(tensor_desc);
  217. ge::TensorUtils::SetSize(tensor_desc, dataSize);
  218. op_desc->AddInputDesc(tensor_desc);
  219. }
  220. static void AddOutputDesc(ge::OpDescPtr op_desc, vector<int64_t> shape, ge::Format format, ge::DataType dataType,
  221. int64_t dataSize = 0) {
  222. ge::GeTensorDesc tensor_desc(ge::GeShape(shape), format, dataType);
  223. InitDefaultTensorDesc(tensor_desc);
  224. ge::TensorUtils::SetSize(tensor_desc, dataSize);
  225. op_desc->AddOutputDesc(tensor_desc);
  226. }
  227. static void AddWeight(ge::NodePtr node_ptr, uint8_t *data, size_t dataLen, vector<int64_t> shape = {},
  228. ge::Format format = ge::FORMAT_NCHW, ge::DataType dataType = ge::DT_FLOAT) {
  229. ge::GeTensorDesc tensor_desc(ge::GeShape(shape), format, dataType);
  230. vector<ge::GeTensorPtr> weigths = ge::OpDescUtils::MutableWeights(node_ptr);
  231. weigths.push_back(std::make_shared<ge::GeTensor>(tensor_desc, data, dataLen));
  232. ge::OpDescUtils::SetWeights(node_ptr, weigths);
  233. }
  234. static ge::OpDescPtr CreateOpDesc() {
  235. auto op_desc = std::make_shared<ge::OpDesc>();
  236. return op_desc;
  237. }
  238. };
  239. class OmeTestOpDescBuilder {
  240. public:
  241. OmeTestOpDescBuilder(ge::OpDescPtr orgOpDesc = nullptr) : orgOpDesc_(orgOpDesc) {
  242. if (orgOpDesc_) {
  243. streamId_ = orgOpDesc_->GetStreamId();
  244. }
  245. }
  246. OmeTestOpDescBuilder &SetStreamId(int64_t streamId) {
  247. streamId_ = streamId;
  248. return *this;
  249. }
  250. OmeTestOpDescBuilder &SetWorkspace(vector<int64_t> workspace) {
  251. workspace_ = workspace;
  252. return *this;
  253. }
  254. OmeTestOpDescBuilder &SetWorkspaceBytes(vector<int64_t> workspaceBytes) {
  255. workspaceBytes_ = workspaceBytes;
  256. return *this;
  257. }
  258. OmeTestOpDescBuilder &SetType(const string &type) {
  259. type_ = type;
  260. return *this;
  261. }
  262. OmeTestOpDescBuilder &SetName(const string &name) {
  263. name_ = name;
  264. return *this;
  265. }
  266. OmeTestOpDescBuilder &SetInputs(vector<int64_t> inputs) {
  267. inputsDataOffeset_ = inputs;
  268. return *this;
  269. }
  270. OmeTestOpDescBuilder &AddInput(int64_t input) {
  271. inputsDataOffeset_.push_back(input);
  272. return *this;
  273. }
  274. OmeTestOpDescBuilder &SetOutputs(vector<int64_t> outputs) {
  275. outputsDataOffeset_ = outputs;
  276. return *this;
  277. }
  278. OmeTestOpDescBuilder &AddOutput(int64_t output) {
  279. outputsDataOffeset_.push_back(output);
  280. return *this;
  281. }
  282. OmeTestOpDescBuilder &SetEventId(int64_t eventId) {
  283. eventId_ = eventId;
  284. return *this;
  285. }
  286. OmeTestOpDescBuilder &Setscopeid(int64_t scopeid) {
  287. scopeid_ = scopeid;
  288. return *this;
  289. }
  290. ge::GeTensorDesc &AddInputDesc(vector<int64_t> shape, ge::Format format, ge::DataType dataType,
  291. int64_t dataSize = 0) {
  292. ge::GeTensorDesc tensor_desc(ge::GeShape(shape), format, dataType);
  293. OmeTestOpUtils::InitDefaultTensorDesc(tensor_desc);
  294. ge::TensorUtils::SetSize(tensor_desc, dataSize);
  295. inputTensorDescs.push_back(tensor_desc);
  296. return inputTensorDescs.back();
  297. }
  298. ge::GeTensorDesc &AddInputDesc(vector<int64_t> shape, ge::Format format, ge::DataType dataType, int64_t realdimcnt,
  299. int64_t dataSize) {
  300. ge::GeTensorDesc tensor_desc(ge::GeShape(shape), format, dataType);
  301. OmeTestOpUtils::InitDefaultTensorDesc(tensor_desc);
  302. ge::TensorUtils::SetSize(tensor_desc, dataSize);
  303. ge::TensorUtils::SetRealDimCnt(tensor_desc, realdimcnt);
  304. inputTensorDescs.push_back(tensor_desc);
  305. return inputTensorDescs.back();
  306. }
  307. ge::GeTensorDesc &AddOutputDesc(vector<int64_t> shape, ge::Format format, ge::DataType dataType,
  308. int64_t dataSize = 0) {
  309. ge::GeTensorDesc tensor_desc(ge::GeShape(shape), format, dataType);
  310. OmeTestOpUtils::InitDefaultTensorDesc(tensor_desc);
  311. ge::TensorUtils::SetSize(tensor_desc, dataSize);
  312. outputTensorDescs.push_back(tensor_desc);
  313. return outputTensorDescs.back();
  314. }
  315. ge::GeTensorDesc &AddOutputDesc(vector<int64_t> shape, ge::Format format, ge::DataType dataType, int64_t realdimcnt,
  316. int64_t dataSize) {
  317. ge::GeTensorDesc tensor_desc(ge::GeShape(shape), format, dataType);
  318. OmeTestOpUtils::InitDefaultTensorDesc(tensor_desc);
  319. ge::TensorUtils::SetSize(tensor_desc, dataSize);
  320. ge::TensorUtils::SetRealDimCnt(tensor_desc, realdimcnt);
  321. outputTensorDescs.push_back(tensor_desc);
  322. return outputTensorDescs.back();
  323. }
  324. ge::GeTensorPtr AddWeight(uint8_t *data, size_t dataLen, vector<int64_t> shape = {},
  325. ge::Format format = ge::FORMAT_NCHW, ge::DataType dataType = ge::DT_FLOAT) {
  326. ge::GeTensorDesc tensor_desc(ge::GeShape(shape), format, dataType);
  327. weights_.emplace_back(std::make_shared<ge::GeTensor>(tensor_desc, data, dataLen));
  328. return weights_.back();
  329. }
  330. ge::NodePtr Finish() {
  331. ge::OpDescPtr op_desc;
  332. if (orgOpDesc_) {
  333. op_desc = orgOpDesc_;
  334. } else {
  335. op_desc = OmeTestOpUtils::CreateOpDesc(); // std::make_shared<ge::OpDesc>(name_, type_);
  336. }
  337. if (!type_.empty()) {
  338. op_desc->SetType(type_);
  339. }
  340. if (!name_.empty()) {
  341. op_desc->SetName(name_);
  342. }
  343. op_desc->SetStreamId(streamId_);
  344. ge::AttrUtils::SetInt(op_desc, "id", 1);
  345. if (eventId_ != -1) {
  346. ge::AttrUtils::SetInt(op_desc, SEND_ATTR_EVENT_ID, eventId_);
  347. }
  348. if (scopeid_ != -1) {
  349. ge::AttrUtils::SetInt(op_desc, "fusion_scope", scopeid_);
  350. }
  351. // ge::AttrUtils::SetInt(op_desc, ATTR_NAME_STREAM_ID, streamId_);
  352. // if(!inputsDataOffeset_.empty())
  353. {
  354. vector<int64_t> inputs;
  355. inputs = op_desc->GetInputOffset();
  356. inputs.insert(inputs.end(), inputsDataOffeset_.begin(), inputsDataOffeset_.end());
  357. op_desc->SetInputOffset(inputs);
  358. }
  359. // if(!outputsDataOffeset_.empty())
  360. {
  361. vector<int64_t> outputs;
  362. outputs = op_desc->GetOutputOffset();
  363. outputs.insert(outputs.end(), outputsDataOffeset_.begin(), outputsDataOffeset_.end());
  364. op_desc->SetOutputOffset(outputs);
  365. }
  366. // if(!workspace_.empty())
  367. {
  368. vector<int64_t> workspace = op_desc->GetWorkspace();
  369. workspace.insert(workspace.end(), workspace_.begin(), workspace_.end());
  370. op_desc->SetWorkspace(workspace);
  371. }
  372. // if(!workspaceBytes_.empty())
  373. {
  374. vector<int64_t> workspaceBytes;
  375. workspaceBytes = op_desc->GetWorkspaceBytes();
  376. workspaceBytes.insert(workspaceBytes.end(), workspaceBytes_.begin(), workspaceBytes_.end());
  377. op_desc->SetWorkspaceBytes(workspaceBytes);
  378. }
  379. for (auto &tensor_desc : inputTensorDescs) {
  380. op_desc->AddInputDesc(tensor_desc);
  381. }
  382. for (auto &tensor_desc : outputTensorDescs) {
  383. op_desc->AddOutputDesc(tensor_desc);
  384. }
  385. static std::shared_ptr<ge::ComputeGraph> graph;
  386. // clear graph
  387. graph = std::make_shared<ge::ComputeGraph>("g");
  388. ge::NodePtr node_op = graph->AddNode(op_desc);
  389. // for(int i=0; i < inputTensorDescs.size(); i++)
  390. for (int i = 0; i < op_desc->GetInputsSize(); i++) {
  391. ge::OpDescPtr src_op_desc = std::make_shared<ge::OpDesc>();
  392. ge::GeTensorDesc src_out_desc;
  393. src_op_desc->AddOutputDesc(src_out_desc);
  394. ge::NodePtr src_node = graph->AddNode(src_op_desc);
  395. if (nullptr == src_node) {
  396. GELOGE(ge::FAILED, "Finish: nullptr == src_node");
  397. }
  398. Status res = ge::GraphUtils::AddEdge(src_node->GetOutDataAnchor(0), node_op->GetInDataAnchor(i));
  399. if (SUCCESS != res) {
  400. GELOGE(ge::FAILED, "Finish: GraphUtils::AddEdge failed");
  401. }
  402. }
  403. {
  404. vector<ge::GeTensorPtr> weights;
  405. weights = ge::OpDescUtils::MutableWeights(node_op);
  406. weights.insert(weights.end(), weights_.begin(), weights_.end());
  407. ge::OpDescUtils::SetWeights(node_op, weights);
  408. }
  409. *this = OmeTestOpDescBuilder(op_desc); // clear up
  410. return node_op;
  411. }
  412. private:
  413. ge::OpDescPtr orgOpDesc_;
  414. int64_t streamId_ = 0;
  415. string type_;
  416. string name_;
  417. vector<int64_t> inputsDataOffeset_; // input
  418. vector<int64_t> outputsDataOffeset_; // output
  419. vector<ge::GeTensorDesc> inputTensorDescs;
  420. vector<ge::GeTensorDesc> outputTensorDescs;
  421. vector<int64_t> workspace_;
  422. vector<int64_t> workspaceBytes_;
  423. vector<ge::GeTensorPtr> weights_;
  424. int64_t eventId_ = -1;
  425. int64_t scopeid_ = -1;
  426. };
  427. #endif // OME_REBUILD_OME_OP_TEST_UTILS_H

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