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.

main.cc 57 kB

5 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332
  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 <dirent.h>
  17. #include <dlfcn.h>
  18. #include <gflags/gflags.h>
  19. #include <sys/types.h>
  20. #include <unistd.h>
  21. #include <cctype>
  22. #include <climits>
  23. #include <cstdlib>
  24. #include <iostream>
  25. #include "common/gflags_util.h"
  26. #include "common/util.h"
  27. #include "common/util/error_manager/error_manager.h"
  28. #include "framework/common/debug/ge_log.h"
  29. #include "ge/ge_api.h"
  30. #include "generator/ge_generator.h"
  31. #include "graph/anchor.h"
  32. #include "graph/debug/ge_attr_define.h"
  33. #include "graph/graph.h"
  34. #include "graph/op_desc.h"
  35. #include "graph/utils/graph_utils.h"
  36. #include "graph/utils/type_utils.h"
  37. #include "init/gelib.h"
  38. #include "ir_build/atc_ir_common.h"
  39. #include "omg/omg.h"
  40. #include "omg/parser/parser_factory.h"
  41. #include "omg/parser/parser_inner_ctx.h"
  42. #include "parser/common/register_tbe.h"
  43. #include "register/op_registry.h"
  44. #include "single_op_parser.h"
  45. using domi::BuildMode;
  46. using domi::OpRegistrationData;
  47. using domi::OpRegistry;
  48. using domi::Status;
  49. using domi::SUCCESS;
  50. using ge::GEN_OM_MODEL;
  51. using ge::GflagsUtils;
  52. using ge::MODEL_TO_JSON;
  53. using ge::ONLY_PRE_CHECK;
  54. using ge::ParseInputShape;
  55. using ge::PBTXT_TO_JSON;
  56. using std::map;
  57. using std::pair;
  58. using std::shared_ptr;
  59. using std::string;
  60. using std::vector;
  61. static bool is_dynamic_input = false;
  62. // 310 limited 8G size
  63. const char *const kGraphMemoryManagerMallocMaxSize = "8*1024*1024*1024";
  64. const char *const kModeSupport = "only support 0(model to framework model), "
  65. "1(framework model to json), 3(only pre-check), 5(pbtxt to json)";
  66. const char *const kModelToJsonSupport = "only support 0(Caffe) 3(TensorFlow)";
  67. // limit available mem size 2G
  68. const long kMinAvailableMem = 2 * 1024 * 1024;
  69. DEFINE_string(model, "", "The model file.");
  70. DEFINE_string(output, "", "The output file path&name.");
  71. DEFINE_int32(framework, -1, "Framework type(0:Caffe; 1:MindSpore; 3:Tensorflow).");
  72. DEFINE_string(weight, "", "Optional; weight file. Required when framework is Caffe.");
  73. DEFINE_string(input_shape, "",
  74. "Optional; shape of input data. Required when framework is caffe "
  75. "or TensorFLow or MindSpore."
  76. "Format: \"input_name1:n1,c1,h1,w1;input_name2:n2,c2,h2,w2\"");
  77. DEFINE_bool(h, false, "show this help message");
  78. DEFINE_string(cal_conf, "", "Optional; the calibration config file.");
  79. DEFINE_string(insert_op_conf, "", "Optional; the config file to insert new op, for example AIPP op.");
  80. DEFINE_string(op_name_map, "", "Optional; custom op name mapping file.");
  81. DEFINE_string(target, "", "Optional; mini.");
  82. DEFINE_string(om, "", "The model file to be converted to json.");
  83. DEFINE_string(json, "", "The output json file path&name which is converted from a model.");
  84. DEFINE_int32(mode, 0,
  85. "Optional; run mode, 0(default): model => framework model; 1: "
  86. "framework model => json; 3: only pre-check; 5: pbtxt => json.");
  87. #if !defined(__ANDROID__) && !defined(ANDROID)
  88. DEFINE_int32(encrypt_mode, -1, "Optional; the encrypt flag. 0: encrypt; -1(default): not encrypt");
  89. DEFINE_string(encrypt_key, "", "Optional; the encrypt_key file.");
  90. DEFINE_string(certificate, "", "Optional; the certificate file.");
  91. DEFINE_string(hardware_key, "", "Optional; the ISV key file.");
  92. DEFINE_string(private_key, "", "Optional; the private key file.");
  93. #endif
  94. DEFINE_string(out_nodes, "",
  95. "Optional; output nodes designated by users."
  96. "Format: \"node_name1:0;node_name1:1;node_name2:0\"");
  97. DEFINE_string(precision_mode, "",
  98. "Optional; precision mode."
  99. "Support force_fp16, allow_mix_precision, allow_fp32_to_fp16, must_keep_origin_dtype.");
  100. DEFINE_string(input_format, "",
  101. "Optional; input_format, format of input data, NCHW;NHWC."
  102. "Format:\"NHWC\"");
  103. DEFINE_string(check_report, "check_result.json", "Optional; the pre-checking report file.");
  104. DEFINE_string(input_fp16_nodes, "",
  105. "Optional; input node datatype is fp16 and format is NC1HWC0."
  106. "Format:\"node_name1;node_name2\"");
  107. DEFINE_string(is_output_adjust_hw_layout, "",
  108. "Optional; Net output node's datatype is fp16 and format is "
  109. "NC1HWC0, or not."
  110. "Format:\"false,true,false,true\"");
  111. DEFINE_string(is_input_adjust_hw_layout, "",
  112. "Optional; Intput node's datatype is fp16 and format is "
  113. "NC1HWC0, or not."
  114. "Format:\"false,true,false,true\"");
  115. DEFINE_string(output_type, "",
  116. "Optional; output type! "
  117. "Support FP32,FP16,INT8,INT16,UINT16,UINT8,INT32,INT64,UINT32,UINT64,DOUBLE.");
  118. DEFINE_string(op_select_implmode, "",
  119. "Optional; op select implmode! "
  120. "Support high_precision, high_performance.");
  121. DEFINE_string(optypelist_for_implmode, "",
  122. "Optional; Nodes need use implmode selected in op_select_implmode "
  123. "Format:\"node_name1,node_name2\"");
  124. DEFINE_string(singleop, "", "Optional; If set, generate single op model with the given json file.");
  125. DEFINE_int32(disable_reuse_memory, 0, "Optional; If set to 1, disable reuse memory when generating if.");
  126. DEFINE_string(auto_tune_mode, "", "Optional; Set tune mode.");
  127. DEFINE_string(soc_version, "", "The soc version.");
  128. DEFINE_string(core_type, "AiCore", "Optional; If set to VectorCore, only use vector core.");
  129. DEFINE_string(aicore_num, "", "Optional; Set aicore num");
  130. DEFINE_string(buffer_optimize, "l2_optimize", "Optional; buffer optimize");
  131. DEFINE_string(fusion_switch_file, "", "Optional; Set fusion switch file path");
  132. DEFINE_string(save_original_model, "", "Optional; enable output original offline model. false(default)");
  133. DEFINE_string(dynamic_batch_size, "",
  134. "Optional; If set, generate dynamic multi batch model. "
  135. "Different batch sizes are split by ','."
  136. "dynamic_batch_size, dynamic_image_size and dynamic_dims can only be set one.");
  137. DEFINE_string(dynamic_image_size, "",
  138. "Optional; If set, generate dynamic multi image size model."
  139. "Different groups of image size are split by ';',"
  140. "while different dimensions of each group are split by ','."
  141. "dynamic_batch_size, dynamic_image_size and dynamic_dims can only be set one.");
  142. DEFINE_string(dynamic_dims, "",
  143. "Optional; If set, generate dynamic input size model. "
  144. "Different groups of size are split by ';', while different dimensions of each group are split by ','."
  145. "dynamic_batch_size, dynamic_image_size and dynamic_dims can only be set one.");
  146. DEFINE_string(enable_small_channel, "0", "Optional; If set to 1, small channel is enabled.");
  147. DEFINE_string(enable_compress_weight, "false",
  148. "Optional; enable compress weight. true: enable; false(default): disable");
  149. DEFINE_string(compress_weight_conf, "", "Optional; the config file to compress weight");
  150. DEFINE_string(enable_single_stream, "", "Optional; enable single stream. true: enable; false(default): disable");
  151. DEFINE_string(log, "null", "Optional; generate atc log. Support debug, info, warning, error, null");
  152. DEFINE_string(dump_mode, "0", "Optional; generate infershape json,only support 1 , 0.");
  153. DEFINE_int32(op_debug_level, 0, "Optional; configure debug level of compiler. 0(default): close debug;"
  154. "1: open TBE compiler, export ccec file and TBE instruction mapping file; 2: open ccec compiler");
  155. DEFINE_string(enable_scope_fusion_passes, "", "Optional; validate the non-general scope fusion pass,"
  156. "multiple names can be set and separated by ','.");
  157. class GFlagUtils {
  158. public:
  159. /**
  160. * @name InitGFlag
  161. * @brief initialize gflag
  162. * @return void
  163. */
  164. static void InitGFlag(int argc, char *argv[]) {
  165. // -help
  166. gflags::SetUsageMessage(
  167. "usage: ./atc <args>\n"
  168. "generate offline model example:\n"
  169. "./atc --model=./alexnet.prototxt --weight=./alexnet.caffemodel \n"
  170. "--framework=0 --output=./domi \n"
  171. "generate offline model for single op example:\n"
  172. "./atc --singleop=./op_list.json --output=./op_model \n"
  173. "===== Basic Functionality =====\n"
  174. "[General]\n"
  175. " --h/help Show this help message\n"
  176. " --mode Run mode. 0(default): generate offline model; 1: convert model to JSON format "
  177. "3: only pre-check; 5: convert pbtxt file to JSON format\n"
  178. "\n[Input]\n"
  179. " --model Model file\n"
  180. " --weight Weight file. Required when framework is Caffe\n"
  181. " --om The model file to be converted to json\n"
  182. " --framework Framework type. 0:Caffe; 1:MindSpore; 3:Tensorflow\n"
  183. " --input_format Format of input data. E.g.: \"NCHW\"\n"
  184. " --input_shape Shape of input data. Separate multiple nodes with semicolons (;)."
  185. "Use double quotation marks (\") to enclose each argument.\n"
  186. " E.g.: \"input_name1:n1,c1,h1,w1;input_name2:n2,c2,h2,w2\"\n"
  187. " --dynamic_batch_size Set dynamic batch size. E.g: \"batchsize1,batchsize2,batchsize3\"\n"
  188. " --dynamic_image_size Set dynamic image size. Separate multiple nodes with semicolons (;)."
  189. "Use double quotation marks (\") to enclose each argument.\n"
  190. " E.g: \"imagesize1_height,imagesize1_width;imagesize2_height,imagesize2_width\"\n"
  191. " --dynamic_dims Set dynamic dims. Separate multiple nodes with semicolons (;)."
  192. "Use double quotation marks (\") to enclose each argument. E.g: \"dims1_n1,dims1_n2;dims2_n1,dims2_n2\"\n"
  193. " --singleop Single op definition file. atc will generate offline "
  194. "model(s) for single op if --singleop is set.\n"
  195. "\n[Output]\n"
  196. " --output Output file path&name(needn't suffix, will add "
  197. ".om automatically). \n"
  198. " If --singleop is set, this arg specifies the directory to "
  199. "which the single op offline model will be generated\n"
  200. " --output_type Set net output type. Support FP32, FP16, UINT8."
  201. "E.g.: FP16, indicates that all out nodes are set to FP16.\n"
  202. " \"node1:0:FP16;node2:1:FP32\", indicates setting the datatype of multiple out nodes.\n"
  203. " --check_report The pre-checking report file. Default value is: "
  204. "\"check_result.json\"\n"
  205. " --json The output json file path&name which is "
  206. "converted from a model\n"
  207. "\n[Target]\n"
  208. " --soc_version The soc version.\n"
  209. " --core_type Set core type AiCore or VectorCore. VectorCore: use vector core. "
  210. "Default value is: AiCore\n"
  211. " --aicore_num Set aicore num\n"
  212. "===== Advanced Functionality =====\n"
  213. "[Feature]\n"
  214. " --out_nodes Output nodes designated by users. Separate multiple nodes with semicolons (;)."
  215. "Use double quotation marks (\") to enclose each argument.\n"
  216. " E.g.: \"node_name1:0;node_name1:1;node_name2:0\"\n"
  217. " --input_fp16_nodes Input node datatype is fp16. Separate multiple nodes with semicolons "
  218. "(;)."
  219. "Use double quotation marks (\") to enclose each argument."
  220. "E.g.: \"node_name1;node_name2\"\n"
  221. " --insert_op_conf Config file to insert new op\n"
  222. " --op_name_map Custom op name mapping file\n"
  223. " Note: A semicolon(;) cannot be included in each "
  224. "path, otherwise the resolved path will not match the expected one.\n"
  225. " --is_input_adjust_hw_layout Intput node datatype is fp16 and format is "
  226. "NC1HWC0, used with input_fp16_nodes E.g.: \"true,true,false,true\"\n"
  227. " --is_output_adjust_hw_layout Net output node datatype is fp16 and format is "
  228. "NC1HWC0, used with out_nodes. E.g.: \"true,true,false,true\"\n"
  229. "\n[Model Tuning]\n"
  230. " --disable_reuse_memory The switch of reuse memory. Default value is : 0."
  231. "0 means reuse memory, 1 means do not reuse memory.\n"
  232. " --fusion_switch_file Set fusion switch file path\n"
  233. " --enable_scope_fusion_passes validate the non-general scope fusion passes,"
  234. "multiple names can be set and separated by ','. E.g.: ScopePass1,ScopePass2,...\n"
  235. " --enable_single_stream Enable single stream. true: enable; false(default): disable\n"
  236. " --enable_small_channel Set enable small channel. 0(default): disable; 1: enable\n"
  237. " --enable_compress_weight Enable compress weight. true: enable; false(default): disable\n"
  238. " --compress_weight_conf Config file to compress weight\n"
  239. " --buffer_optimize Set buffer optimize. \"l2_optimize\" (default). Set \"off_optimize\" to close\n"
  240. "\n[Operator Tuning]\n"
  241. " --precision_mode precision mode, support force_fp16, allow_mix_precision, "
  242. "allow_fp32_to_fp16, must_keep_origin_dtype.\n"
  243. " --auto_tune_mode Set tune mode. E.g.: \"GA,RL\", support configure multiple, spit by ,\n"
  244. " --op_select_implmode Set op select implmode. Support high_precision, high_performance."
  245. "default: high_performance\n"
  246. " --optypelist_for_implmode Appoint which op to select implmode, cooperated with op_select_implmode.\n"
  247. " Separate multiple nodes with commas (,). Use double quotation marks (\") "
  248. " to enclose each argument. E.g.: \"node_name1,node_name2\"\n"
  249. " --op_debug_level Debug enable for TBE operator building.\n"
  250. " 0 (default): Disable debug; 1: Enable TBE pipe_all, "
  251. "and generate the operator CCE file and Python-CCE mapping file (.json);\n"
  252. " 2: Enable TBE pipe_all, generate the operator CCE file and Python-CCE mapping file "
  253. "(.json), and enable the CCE compiler -O0-g.\n"
  254. "\n[Debug]\n"
  255. " --save_original_model Control whether to output original model. E.g.: true: output original model\n"
  256. " --log Generate log with level. Support debug, info, warning, error, null\n"
  257. " --dump_mode The switch of dump json with shape, to be used with mode 1."
  258. "0(default): disable; 1: enable.");
  259. gflags::ParseCommandLineNonHelpFlags(&argc, &argv, true);
  260. // Using gflags to analyze input parameters
  261. GflagsUtils::ChangeHelpFlags(FLAGS_h);
  262. gflags::HandleCommandLineHelpFlags();
  263. }
  264. static Status CheckDumpInfershapeJsonFlags() {
  265. Status ret = CheckFrameWorkValid(FLAGS_framework, FLAGS_weight);
  266. GE_CHK_BOOL_EXEC(ret == domi::SUCCESS, return domi::FAILED,
  267. "check custom aicpu run so failed!");
  268. GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(
  269. FLAGS_weight != "" && !ge::CheckInputPathValid(FLAGS_weight, "--weight"),
  270. return domi::FAILED, "Input parameter[--weight]'s value[%s] is invalid!",
  271. FLAGS_weight.c_str());
  272. return domi::SUCCESS;
  273. }
  274. static Status CheckFlags() {
  275. Status ret = ge::SUCCESS;
  276. // No model file information passed in
  277. GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(
  278. FLAGS_model == "",
  279. ErrorManager::GetInstance().ATCReportErrMessage("E10004", {"parameter"}, {"model"});
  280. ret = ge::FAILED, "Input parameter[--model]'s value is empty!");
  281. // check param disable_reuse_memory
  282. GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(
  283. ge::CheckDisableReuseMemoryParamValid(to_string(FLAGS_disable_reuse_memory)) != ge::SUCCESS,
  284. ret = ge::FAILED, "check disable_reuse_memory failed!");
  285. // check optypelist_for_implmode and op_select_implmode
  286. GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(
  287. ge::CheckImplmodeParamValid(FLAGS_optypelist_for_implmode,
  288. FLAGS_op_select_implmode) != ge::SUCCESS,
  289. ret = ge::FAILED, "check optypelist_for_implmode and op_select_implmode failed!");
  290. // No output file information passed in
  291. GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(
  292. FLAGS_mode == GEN_OM_MODEL && FLAGS_output == "",
  293. ErrorManager::GetInstance().ATCReportErrMessage("E10004", {"parameter"}, {"output"});
  294. ret = ge::FAILED, "Input parameter[--output]'s value is empty!");
  295. GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(
  296. CheckFrameWorkValid(FLAGS_framework, FLAGS_weight) != ge::SUCCESS,
  297. ret = ge::FAILED,
  298. "CheckFrameWorkValid failed");
  299. GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(
  300. ge::CheckDynamicInputParamValid(FLAGS_dynamic_batch_size, FLAGS_dynamic_image_size,
  301. FLAGS_dynamic_dims, FLAGS_input_shape,
  302. FLAGS_input_format, is_dynamic_input) != ge::SUCCESS,
  303. ret = ge::FAILED, "check dynamic size(batch size, image size or dims) failed!");
  304. GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(
  305. !FLAGS_insert_op_conf.empty() && !FLAGS_dynamic_dims.empty(),
  306. ErrorManager::GetInstance().ATCReportErrMessage("E10001",
  307. {"parameter", "value", "reason"},
  308. {"--insert_op_conf", FLAGS_insert_op_conf,
  309. "dynamic dims function does not support aipp"});
  310. ret = ge::FAILED, "dynamic dims function does not support aipp");
  311. #if !defined(__ANDROID__) && !defined(ANDROID)
  312. GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(!CheckEncryptModeValid(FLAGS_encrypt_mode), ret = ge::FAILED,
  313. "encrypt_mode %d not valid!!", FLAGS_encrypt_mode);
  314. if (FLAGS_encrypt_mode == 0) { // Encryption mode
  315. GELOGI("ge will run with encrypt!");
  316. GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(!ge::CheckInputPathValid(FLAGS_encrypt_key), ret = ge::FAILED,
  317. "encrypt_key file not found!!");
  318. GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(!ge::CheckInputPathValid(FLAGS_certificate), ret = ge::FAILED,
  319. "certificate file not found!!");
  320. GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(!ge::CheckInputPathValid(FLAGS_hardware_key), ret = ge::FAILED,
  321. "hardware_key file not found!!");
  322. GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(!ge::CheckInputPathValid(FLAGS_private_key), ret = ge::FAILED,
  323. "private_key file not found!!");
  324. } else { // No encryption
  325. GELOGI("ge will run without encrypt!");
  326. }
  327. #endif
  328. /**
  329. * Check the validity of the I / O file path
  330. */
  331. GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(
  332. FLAGS_model != "" && !ge::CheckInputPathValid(FLAGS_model, "--model"), ret = ge::FAILED,
  333. "model file %s not found!!", FLAGS_model.c_str());
  334. GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(
  335. FLAGS_weight != "" && !ge::CheckInputPathValid(FLAGS_weight, "--weight"),
  336. ret = ge::FAILED, "weight file %s not found!!",
  337. FLAGS_weight.c_str());
  338. GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(
  339. FLAGS_cal_conf != "" && !ge::CheckInputPathValid(FLAGS_cal_conf, "--cal_conf"),
  340. ret = ge::FAILED, "calibration config file %s not found!!",
  341. FLAGS_cal_conf.c_str());
  342. GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(
  343. FLAGS_op_name_map != "" && !ge::CheckInputPathValid(FLAGS_op_name_map, "--op_name_map"),
  344. ret = ge::FAILED, "op config file %s not found!!",
  345. FLAGS_op_name_map.c_str());
  346. GE_CHK_BOOL_EXEC(ge::CheckInsertOpConfParamValid(std::string(FLAGS_insert_op_conf)) == ge::SUCCESS,
  347. ret = ge::FAILED, "check insert op conf failed!");
  348. GE_CHK_BOOL_EXEC(ge::CheckCompressWeightParamValid(
  349. FLAGS_enable_compress_weight, FLAGS_compress_weight_conf) == ge::SUCCESS,
  350. ret = ge::FAILED, "check compress weight failed!");
  351. GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(
  352. !ge::CheckOutputPathValid(FLAGS_check_report, "--check_report"), ret = ge::FAILED,
  353. "check_report file %s not found!!", FLAGS_check_report.c_str());
  354. GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(
  355. FLAGS_mode == GEN_OM_MODEL && FLAGS_output != "" &&
  356. (!ge::CheckOutputPathValid(FLAGS_output, "--output") || !CheckPathWithName(FLAGS_output)),
  357. ret = ge::FAILED, "output path %s is not valid!!", FLAGS_output.c_str());
  358. GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(
  359. FLAGS_save_original_model != "" &&
  360. FLAGS_save_original_model != "true" &&
  361. FLAGS_save_original_model != "false",
  362. ErrorManager::GetInstance().ATCReportErrMessage(
  363. "E10005", {"parameter", "value"}, {"save_original_model", FLAGS_save_original_model});
  364. ret = ge::FAILED,
  365. "Input parameter[--save_original_model]'s value[%s] must be true or false.",
  366. FLAGS_save_original_model.c_str());
  367. GE_CHK_BOOL_EXEC(ge::CheckBufferOptimizeParamValid(FLAGS_buffer_optimize) == ge::SUCCESS,
  368. ret = ge::FAILED, "check output type failed!");
  369. GE_CHK_BOOL_EXEC(
  370. ge::CheckEnableSingleStreamParamValid(std::string(FLAGS_enable_single_stream)) == ge::SUCCESS,
  371. ret = ge::FAILED, "check enable single stream failed!");
  372. return ret;
  373. }
  374. /**
  375. * Verifying the parameters of converting model to JSON
  376. * 1. Fmk_model
  377. * 2. out_json
  378. **/
  379. static Status CheckConverJsonParamFlags() {
  380. Status ret = ge::SUCCESS;
  381. // No model path passed in
  382. GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(FLAGS_om == "",
  383. ErrorManager::GetInstance().ATCReportErrMessage("E10004", {"parameter"}, {"om"});
  384. ret = ge::FAILED,
  385. "Input parameter[--om]'s value is empty!!");
  386. // JSON path not passed in
  387. GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(FLAGS_json == "",
  388. ErrorManager::GetInstance().ATCReportErrMessage("E10004", {"parameter"}, {"json"});
  389. ret = ge::FAILED,
  390. "Input parameter[--json]'s value is empty!!");
  391. // Check if the model path is valid
  392. GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(
  393. FLAGS_om != "" && !ge::CheckInputPathValid(FLAGS_om, "--om"),
  394. ret = ge::FAILED,
  395. "model file path is invalid: %s.", FLAGS_om.c_str());
  396. // Check whether the JSON path is valid
  397. GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(
  398. FLAGS_json != "" && !ge::CheckOutputPathValid(FLAGS_json, "--json"),
  399. ret = ge::FAILED,
  400. "json file path is invalid: %s.", FLAGS_json.c_str());
  401. return ret;
  402. }
  403. /**
  404. * Check command line parameters for explicit settings
  405. * true: Explicit setup
  406. * false: Not set up
  407. * */
  408. static bool CheckFlagSet(string flag) {
  409. gflags::CommandLineFlagInfo info;
  410. return !(gflags::GetCommandLineFlagInfo(flag.c_str(), &info) && info.is_default);
  411. }
  412. private:
  413. static bool CheckEncryptModeValid(const int encrypt_mode) {
  414. #if !defined(__ANDROID__) && !defined(ANDROID)
  415. if (encrypt_mode != 0 && encrypt_mode != -1) {
  416. DOMI_LOGE("encrypt mode must be 0 or -1");
  417. return false;
  418. }
  419. #else
  420. if (encrypt_mode != -1) {
  421. DOMI_LOGE("encrypt mode must be -1");
  422. return false;
  423. }
  424. #endif
  425. return true;
  426. }
  427. static Status CheckFrameWorkValid(int framework, const std::string weight_file) {
  428. if (framework != (int32_t)domi::CAFFE && framework != (int32_t)domi::TENSORFLOW &&
  429. framework != (int32_t)domi::MINDSPORE && framework != (int32_t)domi::ONNX) {
  430. // No framework information was passed in or the entered framework is illegal
  431. ErrorManager::GetInstance().ATCReportErrMessage(
  432. "E10007", {"parameter", "support"},
  433. {"framework", "0(Caffe) or 1(MindSpore) or 3(TensorFlow)"});
  434. DOMI_LOGE("Input parameter[--framework] is mandatory and it's value must be: "
  435. "0(Caffe) or 1(MindSpore) or 3(TensorFlow).");
  436. return domi::PARAM_INVALID;
  437. }
  438. if ((framework == (int32_t)domi::CAFFE) && (weight_file == "")) {
  439. ErrorManager::GetInstance().ATCReportErrMessage("E10008", {"parameter"}, {"weight"});
  440. DOMI_LOGE("Input parameter[--weight]'s value is empty when framework is 0(CAFFE)!");
  441. return domi::PARAM_INVALID;
  442. }
  443. if ((framework == (int32_t)domi::TENSORFLOW) && (weight_file != "")) {
  444. GELOGW("Parameter weight is ignored for TensorFlow.");
  445. }
  446. if ((framework == (int32_t)domi::ONNX) && (weight_file != "")) {
  447. GELOGW("Parameter weight is ignored for Onnx.");
  448. }
  449. return domi::SUCCESS;
  450. }
  451. static bool CheckPathWithName(const std::string &fileName) {
  452. // Determine file path length
  453. if (fileName.size() > static_cast<int>(PATH_MAX)) {
  454. ErrorManager::GetInstance().ATCReportErrMessage(
  455. "E10021", {"parameter", "size"}, {"output", std::to_string(PATH_MAX)});
  456. GELOGE(ge::FAILED, "Input parameter[--output]'s path is too long, it must be less than %d", PATH_MAX);
  457. return false;
  458. }
  459. // Find the last separator
  460. int slashPosition = fileName.size() - 1;
  461. for (; slashPosition >= 0; slashPosition--) {
  462. if (fileName[slashPosition] == '\\' || fileName[slashPosition] == '/') {
  463. break;
  464. }
  465. }
  466. // Failure if no filename follows the path
  467. if (slashPosition == static_cast<int>(fileName.size() - 1)) {
  468. ErrorManager::GetInstance().ATCReportErrMessage("E10022", {"parameter", "filename"}, {"output", fileName});
  469. DOMI_LOGE("Input parameter[--output]'s path[%s] not include file name", fileName.c_str());
  470. return false;
  471. }
  472. return true;
  473. }
  474. };
  475. void SetDynamicInputSizeOptions() {
  476. if (!FLAGS_dynamic_batch_size.empty()) {
  477. domi::GetContext().dynamic_batch_size = FLAGS_dynamic_batch_size;
  478. }
  479. if (!FLAGS_dynamic_image_size.empty()) {
  480. domi::GetContext().dynamic_image_size = FLAGS_dynamic_image_size;
  481. }
  482. if (!FLAGS_dynamic_dims.empty()) {
  483. domi::GetContext().dynamic_dims = FLAGS_dynamic_dims;
  484. }
  485. }
  486. /// Validate the non-general scope fusion pass.
  487. /// The parameter is set to the name of the fusion rule.
  488. /// Multiple names can be set and separated by ",".
  489. void SetEnableScopeFusionPasses(const std::string pass_names) {
  490. ge::GetParserContext().enable_scope_fusion_passes = pass_names;
  491. }
  492. static bool CheckInputFormat() {
  493. if (FLAGS_input_format.empty()) {
  494. // Set default format
  495. if (FLAGS_framework == static_cast<int32_t>(domi::TENSORFLOW)) {
  496. FLAGS_input_format = "NHWC";
  497. } else {
  498. FLAGS_input_format = "NCHW";
  499. }
  500. return true;
  501. } else if ((FLAGS_framework == static_cast<int32_t>(domi::CAFFE))) { // caffe
  502. if (ge::caffe_support_input_format.find(FLAGS_input_format) != ge::caffe_support_input_format.end()) {
  503. return true;
  504. }
  505. // only support NCHW ND
  506. ErrorManager::GetInstance().ATCReportErrMessage(
  507. "E10001", {"parameter", "value", "reason"}, {"--input_format", FLAGS_input_format, ge::kCaffeFormatSupport});
  508. GELOGE(ge::FAILED,
  509. "Invalid value for --input_format[%s], %s.", FLAGS_input_format.c_str(), ge::kCaffeFormatSupport);
  510. return false;
  511. } else if ((FLAGS_framework == static_cast<int32_t>(domi::TENSORFLOW))) { // tf
  512. if (ge::tf_support_input_format.find(FLAGS_input_format) != ge::tf_support_input_format.end()) {
  513. return true;
  514. }
  515. // only support NCHW NHWC ND NCDHW NDHWC
  516. ErrorManager::GetInstance().ATCReportErrMessage(
  517. "E10001", {"parameter", "value", "reason"}, {"--input_format", FLAGS_input_format, ge::kTFFormatSupport});
  518. GELOGE(ge::FAILED,
  519. "Invalid value for --input_format[%s], %s.", FLAGS_input_format.c_str(), ge::kTFFormatSupport);
  520. return false;
  521. } else if (FLAGS_framework == static_cast<int32_t>(domi::ONNX)) {
  522. if (ge::onnx_support_input_format.find(FLAGS_input_format) != ge::onnx_support_input_format.end()) {
  523. return true;
  524. }
  525. // only support NCHW ND
  526. ErrorManager::GetInstance().ATCReportErrMessage(
  527. "E10001", {"parameter", "value", "reason"}, {"--input_format", FLAGS_input_format, ge::kONNXFormatSupport});
  528. GELOGE(ge::FAILED,
  529. "Invalid value for --input_format[%s], %s.", FLAGS_input_format.c_str(), ge::kONNXFormatSupport);
  530. return false;
  531. }
  532. return true;
  533. }
  534. #if !defined(__ANDROID__) && !defined(ANDROID)
  535. static void GetCustomOpPath(std::string &customop_path) {
  536. GELOGI("Enter get custom op path schedule");
  537. std::string fmk_type = ge::TypeUtils::FmkTypeToSerialString(static_cast<domi::FrameworkType>(FLAGS_framework));
  538. GELOGI("Framework type is %s.", fmk_type.c_str());
  539. const char *path_env = std::getenv("ASCEND_OPP_PATH");
  540. if (path_env != nullptr) {
  541. std::string path = path_env;
  542. customop_path = (path + "/framework/custom" + "/:") + (path + "/framework/built-in/" + fmk_type);
  543. GELOGI("Get custom so path from env : %s", path_env);
  544. return;
  545. }
  546. std::string path_base = ge::GELib::GetPath();
  547. GELOGI("path_base is %s", path_base.c_str());
  548. path_base = path_base.substr(0, path_base.rfind('/'));
  549. path_base = path_base.substr(0, path_base.rfind('/') + 1);
  550. customop_path = (path_base + "ops/framework/custom" + "/:") + (path_base + "ops/framework/built-in/" + fmk_type);
  551. return;
  552. }
  553. void GetPluginSoFileList(const string &path, vector<string> &fileList, string &caffe_parser_path) {
  554. // Support to split multiple so directories by ":"
  555. GELOGI("path is %s", path.c_str());
  556. vector<string> v_path = ge::StringUtils::Split(path, ':');
  557. for (size_t i = 0; i < v_path.size(); ++i) {
  558. ge::FindParserSo(v_path[i], fileList, caffe_parser_path);
  559. GELOGI("CustomOpLib full name = %s", v_path[i].c_str());
  560. }
  561. }
  562. void LoadModelParserLib(std::string caffe_parser_path) {
  563. if (FLAGS_framework == static_cast<int32_t>(domi::TENSORFLOW)) {
  564. void *tf_handle = dlopen("libfmk_parser.so", RTLD_NOW | RTLD_GLOBAL);
  565. if (tf_handle == nullptr) {
  566. GELOGW("dlopen fmk library [libfmk_parser.so] failed.");
  567. return;
  568. }
  569. GELOGI("plugin load libfmk_parser.so success.");
  570. } else if (FLAGS_framework == static_cast<int32_t>(domi::CAFFE)) {
  571. // What we are dealing with here is that the user modifies the caffe.proto scenario.
  572. // If no lib_Caffe_Parser.so is found under the plugin path, use the default lib_Caffe_Parser.so path.
  573. caffe_parser_path = caffe_parser_path.empty() ? "lib_caffe_parser.so" : caffe_parser_path;
  574. void *handle = dlopen(caffe_parser_path.c_str(), RTLD_NOW | RTLD_GLOBAL);
  575. if (handle == nullptr) {
  576. GELOGW("dlopen failed, plugin name:%s. Message(%s).", caffe_parser_path.c_str(), dlerror());
  577. return;
  578. }
  579. GELOGI("plugin load %s success.", caffe_parser_path.c_str());
  580. // According to the dependency, the Caffe parsing module of the framework is loaded here( libfmk_parser.so).
  581. // (depend on the lib_caffe_parser.so)
  582. void *fmk_handle = dlopen("libfmk_parser.so", RTLD_NOW | RTLD_GLOBAL);
  583. if (fmk_handle == nullptr) {
  584. GELOGW("dlopen fmk library [libfmk_parser.so] failed.");
  585. if (dlclose(handle) != 0) {
  586. GELOGW("dlclose lib_caffe_parser.so failed.");
  587. }
  588. return;
  589. }
  590. GELOGI("plugin load libfmk_parser.so success.");
  591. } else if (FLAGS_framework == static_cast<int32_t>(domi::ONNX)) {
  592. void *handle = dlopen("libfmk_onnx_parser.so", RTLD_NOW | RTLD_GLOBAL);
  593. if (handle == nullptr) {
  594. GELOGW("dlopen fmk library [libfmk_onnx_parser.so] failed.");
  595. return;
  596. }
  597. GELOGI("plugin load libfmk_onnx_parser.so success.");
  598. } else {
  599. GELOGW("Framework:%s is not support.",
  600. ge::TypeUtils::FmkTypeToSerialString(static_cast<domi::FrameworkType>(FLAGS_framework)).c_str());
  601. return;
  602. }
  603. return;
  604. }
  605. void LoadCustomOpLib(bool need_load_ops_plugin) {
  606. std::string plugin_path;
  607. GetCustomOpPath(plugin_path);
  608. vector<string> fileList;
  609. string caffe_parser_path = "";
  610. // whether there are files in the plugin so path
  611. GetPluginSoFileList(plugin_path, fileList, caffe_parser_path);
  612. // no file
  613. if (fileList.empty() && caffe_parser_path.empty()) {
  614. GELOGW("can not find any plugin file in plugin_path: %s", plugin_path.c_str());
  615. }
  616. LoadModelParserLib(caffe_parser_path);
  617. if (!need_load_ops_plugin) {
  618. GELOGI("No need to load ops plugin so.");
  619. return;
  620. }
  621. OpRegistry::Instance()->registrationDatas.clear();
  622. // load other so files except lib_caffe_parser.so in the plugin so path
  623. for (auto elem : fileList) {
  624. ge::StringUtils::Trim(elem);
  625. void *handle = dlopen(elem.c_str(), RTLD_NOW | RTLD_GLOBAL);
  626. if (handle == nullptr) {
  627. GELOGW("dlopen failed, plugin name:%s. Message(%s).", elem.c_str(), dlerror());
  628. } else {
  629. GELOGI("plugin load %s success.", elem.c_str());
  630. }
  631. }
  632. std::vector<OpRegistrationData> registrationDatas = OpRegistry::Instance()->registrationDatas;
  633. for (OpRegistrationData reg_data : registrationDatas) {
  634. if (reg_data.GetFrameworkType() == static_cast<domi::FrameworkType>(FLAGS_framework)) {
  635. (void)ge::OpRegistrationTbe::Instance()->Finalize(reg_data);
  636. (void)OpRegistry::Instance()->Register(reg_data);
  637. }
  638. }
  639. }
  640. void SaveCustomCaffeProtoPath() {
  641. GELOGI("Enter save custom caffe proto path.");
  642. std::string path_base = ge::GELib::GetPath();
  643. GELOGI("path_base is %s", path_base.c_str());
  644. path_base = path_base.substr(0, path_base.rfind('/'));
  645. path_base = path_base.substr(0, path_base.rfind('/') + 1);
  646. ge::GetParserContext().caffe_proto_path = path_base + "include/proto/";
  647. string customop_path;
  648. const char *path_env = std::getenv("ASCEND_OPP_PATH");
  649. if (path_env != nullptr) {
  650. std::string path = path_env;
  651. customop_path = path + "/framework/custom/caffe/";
  652. GELOGI("Get custom proto path from env : %s", path_env);
  653. ge::GetParserContext().custom_proto_path = customop_path;
  654. return;
  655. }
  656. customop_path = path_base + "ops/framework/custom/caffe/";
  657. ge::GetParserContext().custom_proto_path = customop_path;
  658. return;
  659. }
  660. #endif
  661. Status CreateInputsForInference(const ge::Graph &graph, vector<ge::GeTensor> &inputs) {
  662. auto compute_graph = ge::GraphUtils::GetComputeGraph(graph);
  663. GE_CHECK_NOTNULL(compute_graph);
  664. for (ge::NodePtr &input_node : compute_graph->GetAllNodes()) {
  665. GE_CHECK_NOTNULL(input_node);
  666. ge::OpDescPtr op = input_node->GetOpDesc();
  667. GE_CHECK_NOTNULL(op);
  668. if (op->GetType() == ge::DATA) {
  669. GELOGI("Data op inputDesc size is: %zu", op->GetAllInputsDesc().size());
  670. ge::GeTensorDesc tensor = op->GetInputDesc(0);
  671. string data_op_name = op->GetName();
  672. GELOGI("Data op name is: %s", data_op_name.c_str());
  673. ge::GeShape data_shape;
  674. auto iter = domi::GetContext().input_dims.find(data_op_name);
  675. if (iter != domi::GetContext().input_dims.end()) {
  676. data_shape = ge::GeShape(iter->second);
  677. GELOGI("Data op get shape from Context.");
  678. } else {
  679. data_shape = tensor.GetShape();
  680. GELOGI("Data op get shape from InputDesc in geir graph.");
  681. }
  682. ge::DataType data_type = tensor.GetDataType();
  683. string data_type_str = ge::TypeUtils::DataTypeToSerialString(data_type);
  684. GELOGI("Data op get data type:%s from InputDesc in geir graph.", data_type_str.c_str());
  685. ge::GeTensor input_tensor;
  686. ge::GeTensorDesc desc(data_shape, ge::Format(domi::GetContext().format), data_type);
  687. input_tensor.SetTensorDesc(desc);
  688. inputs.push_back(input_tensor);
  689. }
  690. }
  691. GELOGI("Build ME model, inputs size is: %zu", inputs.size());
  692. return ge::SUCCESS;
  693. }
  694. domi::Status GenerateInfershapeJson() {
  695. if (!CheckInputFormat()) {
  696. GELOGE(ge::FAILED, "Check input_format failed");
  697. return domi::FAILED;
  698. }
  699. Status ret = GFlagUtils::CheckDumpInfershapeJsonFlags();
  700. GE_CHK_BOOL_EXEC(ret == domi::SUCCESS, return domi::FAILED, "Check flags failed!");
  701. ge::GeGenerator ge_generator;
  702. std::map<string, string> options;
  703. ge::Status geRet = ge_generator.Initialize(options, domi::GetContext());
  704. if (geRet != ge::SUCCESS) {
  705. DOMI_LOGE("GeGenerator initialize failed!");
  706. return domi::FAILED;
  707. }
  708. ge::Graph graph;
  709. std::map<string, string> atc_params;
  710. atc_params.insert(std::pair<string, string>("input_format", FLAGS_input_format));
  711. ret = ParseGraph(graph, atc_params, FLAGS_om.c_str(), FLAGS_weight.c_str(), (domi::FrameworkType) FLAGS_framework,
  712. "", FLAGS_target.c_str(), (ge::RunMode) FLAGS_mode, false);
  713. if (ret != ge::SUCCESS) {
  714. DOMI_LOGE("ATC Parse graph domi::FAILED");
  715. (void)ge_generator.Finalize();
  716. return domi::FAILED;
  717. }
  718. geRet = ge_generator.GenerateInfershapeGraph(graph);
  719. if (geRet != ge::SUCCESS) {
  720. DOMI_LOGE("ATC GenerateInfershapeJson failed");
  721. (void)ge_generator.Finalize();
  722. return domi::FAILED;
  723. }
  724. if (DumpInfershapeJson(graph, FLAGS_json.c_str()) != SUCCESS) {
  725. DOMI_LOGE("ATC DumpInfershapeJson failed");
  726. (void)ge_generator.Finalize();
  727. return domi::FAILED;
  728. }
  729. (void)ge_generator.Finalize();
  730. return ge::SUCCESS;
  731. }
  732. static Status ConvertModelToJson(int fwk_type, const string &model_file, const string &json_file) {
  733. Status ret = ge::SUCCESS;
  734. if (fwk_type == -1) {
  735. ret = ge::ConvertOmModelToJson(model_file.c_str(), json_file.c_str());
  736. return ret;
  737. }
  738. if ((fwk_type != domi::TENSORFLOW) && (fwk_type != domi::CAFFE) && (fwk_type != domi::ONNX)) {
  739. ErrorManager::GetInstance().ATCReportErrMessage(
  740. "E10001", {"parameter", "value", "reason"},
  741. {"--framework", std::to_string(fwk_type), kModelToJsonSupport});
  742. GELOGE(ge::FAILED, "Invalid value for --framework[%d], %s.", fwk_type, kModelToJsonSupport);
  743. ret = ge::FAILED;
  744. }
  745. if (FLAGS_dump_mode != "0" && FLAGS_dump_mode != "1") {
  746. ErrorManager::GetInstance().ATCReportErrMessage("E10006", {"parameter"}, {"dump_mode"});
  747. GELOGE(ge::FAILED, "Input parameter[--dump_mode]'s value must be 1 or 0.");
  748. ret = ge::FAILED;
  749. }
  750. if (ret != ge::SUCCESS) return ret;
  751. // Need to save caffe.proto path
  752. SaveCustomCaffeProtoPath();
  753. if (FLAGS_dump_mode == "0") {
  754. // Caffe or tf model to json depend on lib_caffe_parser.so or libfmk_parser.so.
  755. LoadCustomOpLib(false);
  756. ret = ge::ConvertFwkModelToJson((domi::FrameworkType)fwk_type, model_file.c_str(), json_file.c_str());
  757. } else if (FLAGS_dump_mode == "1") {
  758. // Caffe or tf model to json depend on lib_caffe_parser.so or libfmk_parser.so and ops plugin so.
  759. LoadCustomOpLib(true);
  760. ret = GenerateInfershapeJson();
  761. }
  762. return ret;
  763. }
  764. domi::Status GenerateModel(std::map<string, string> &options, std::string output) {
  765. ge::GeGenerator ge_generator;
  766. ge::Status geRet = ge::SUCCESS;
  767. std::shared_ptr<ge::GELib> instance_ptr = ge::GELib::GetInstance();
  768. if (instance_ptr == nullptr || !instance_ptr->InitFlag()) {
  769. geRet = ge::GELib::Initialize(options);
  770. if (geRet != ge::SUCCESS) {
  771. DOMI_LOGE("GE initialize failed!");
  772. return domi::FAILED;
  773. }
  774. }
  775. geRet = ge_generator.Initialize(options, domi::GetContext());
  776. if (geRet != ge::SUCCESS) {
  777. DOMI_LOGE("GeGenerator initialize failed!");
  778. (void)ge::GELib::GetInstance()->Finalize();
  779. return domi::FAILED;
  780. }
  781. ge::Graph graph;
  782. std::vector<ge::GeTensor> inputs;
  783. if (FLAGS_framework == domi::MINDSPORE) {
  784. // load model from file
  785. ge::Model load_model = ge::Model("loadmodel", "version2");
  786. auto ret1 = load_model.LoadFromFile(FLAGS_model);
  787. if (ret1 != ge::GRAPH_SUCCESS) {
  788. ErrorManager::GetInstance().ATCReportErrMessage("E10041", {"parameter"}, {FLAGS_model});
  789. DOMI_LOGE("Load model from %s failed, please check model file or "
  790. "input parameter[--framework] is correct", FLAGS_model.c_str());
  791. (void)ge_generator.Finalize();
  792. (void)ge::GELib::GetInstance()->Finalize();
  793. return domi::FAILED;
  794. }
  795. graph = load_model.GetGraph();
  796. GE_CHK_STATUS_EXEC(ge::InitDomiOmgContext(FLAGS_input_shape, FLAGS_input_format, "", is_dynamic_input),
  797. GELOGE(ge::FAILED, "ATC Generate call InitDomiOmgContext ret fail");
  798. (void)ge_generator.Finalize(); (void)ge::GELib::GetInstance()->Finalize(); return domi::FAILED);
  799. Status ret = CreateInputsForInference(graph, inputs);
  800. if (ret != ge::SUCCESS) {
  801. GELOGE(ge::FAILED, "create inputs for inference failed.");
  802. (void)ge_generator.Finalize();
  803. (void)ge::GELib::GetInstance()->Finalize();
  804. return domi::FAILED;
  805. }
  806. } else {
  807. std::map<string, string> atc_params;
  808. atc_params.insert(std::pair<string, string>("input_shape", FLAGS_input_shape));
  809. atc_params.insert(std::pair<string, string>("out_nodes", FLAGS_out_nodes));
  810. atc_params.insert(std::pair<string, string>("input_format", FLAGS_input_format));
  811. atc_params.insert(std::pair<string, string>("check_report", FLAGS_check_report));
  812. atc_params.insert(std::pair<string, string>("input_fp16_nodes", FLAGS_input_fp16_nodes));
  813. atc_params.insert(std::pair<string, string>("is_input_adjust_hw_layout", FLAGS_is_input_adjust_hw_layout));
  814. atc_params.insert(std::pair<string, string>("is_output_adjust_hw_layout", FLAGS_is_output_adjust_hw_layout));
  815. atc_params.insert(std::pair<string, string>("compress_weight_conf", FLAGS_compress_weight_conf));
  816. atc_params.insert(std::pair<string, string>(string(ge::OUTPUT_DATATYPE), FLAGS_output_type));
  817. atc_params.insert(std::pair<string, string>("output", output));
  818. Status ret =
  819. ParseGraph(graph, atc_params, FLAGS_model.c_str(), FLAGS_weight.c_str(), (domi::FrameworkType)FLAGS_framework,
  820. FLAGS_op_name_map.c_str(), FLAGS_target.c_str(), (ge::RunMode)FLAGS_mode, is_dynamic_input);
  821. // in ONLY_PRE_CHECK mode, pre-checking report has already saved in ParseGraph
  822. if (FLAGS_mode == ge::ONLY_PRE_CHECK) {
  823. (void)ge_generator.Finalize();
  824. (void)ge::GELib::GetInstance()->Finalize();
  825. if (ret != ge::SUCCESS) {
  826. DOMI_LOGE("ATC precheck fail.");
  827. return domi::FAILED;
  828. }
  829. return domi::SUCCESS;
  830. }
  831. if (ret != ge::SUCCESS) {
  832. DOMI_LOGE("ATC Parse graph domi::FAILED");
  833. DOMI_LOGE("ATC Generate execute failed"); // Duplicate log. (for test case
  834. (void)ge_generator.Finalize();
  835. (void)ge::GELib::GetInstance()->Finalize();
  836. return domi::FAILED;
  837. }
  838. if (ge::SetOutputNodeInfo(graph, FLAGS_output_type, "") != domi::SUCCESS) {
  839. DOMI_LOGE("Set output node info fail.");
  840. (void)ge_generator.Finalize();
  841. (void)ge::GELib::GetInstance()->Finalize();
  842. return domi::FAILED;
  843. }
  844. }
  845. geRet = ge_generator.GenerateOfflineModel(graph, output, inputs);
  846. if (geRet != ge::SUCCESS) {
  847. DOMI_LOGE("GE GenerateOfflineModel execute failed");
  848. DOMI_LOGE("ATC Generate execute failed"); // Duplicate log. (for test case
  849. // checking error log)
  850. (void)ge_generator.Finalize();
  851. (void)ge::GELib::GetInstance()->Finalize();
  852. return domi::FAILED;
  853. }
  854. (void)ge_generator.Finalize();
  855. (void)ge::GELib::GetInstance()->Finalize();
  856. return ge::SUCCESS;
  857. }
  858. static void SetEnvForSingleOp(std::map<string, string> &options) {
  859. string flag_on = "1";
  860. string flag_off = "0";
  861. options.emplace(ge::GE_FE_FLAG, flag_on);
  862. options.emplace(ge::STREAM_NUM, "1"); // single op only use one stream
  863. options.emplace(ge::RUN_FLAG, flag_off);
  864. options.emplace(ge::OPTION_GRAPH_RUN_MODE, flag_off);
  865. options.emplace(ge::SINGLE_OP_FLAG, flag_on);
  866. options.emplace(ge::PRECISION_MODE, FLAGS_precision_mode);
  867. options.emplace(ge::SOC_VERSION, FLAGS_soc_version);
  868. options.emplace(ge::CORE_TYPE, FLAGS_core_type);
  869. options.emplace(ge::AICORE_NUM, FLAGS_aicore_num);
  870. options.emplace(ge::OP_SELECT_IMPL_MODE, FLAGS_op_select_implmode);
  871. options.emplace(ge::OPTYPELIST_FOR_IMPLMODE, FLAGS_optypelist_for_implmode);
  872. options.emplace(ge::AUTO_TUNE_MODE, FLAGS_auto_tune_mode);
  873. options.emplace(ge::GRAPH_MEMORY_MAX_SIZE, kGraphMemoryManagerMallocMaxSize);
  874. options.emplace(ge::OP_DEBUG_LEVEL, to_string(FLAGS_op_debug_level));
  875. }
  876. domi::Status GenerateSingleOp(const std::string& json_file_path) {
  877. if (!FLAGS_output.empty() && !ge::CheckOutputPathValid(FLAGS_output, "--output")) {
  878. DOMI_LOGE("output path %s is not valid!", FLAGS_output.c_str());
  879. return domi::FAILED;
  880. }
  881. // check optypelist_for_implmode and op_select_implmode
  882. GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(
  883. ge::CheckImplmodeParamValid(FLAGS_optypelist_for_implmode, FLAGS_op_select_implmode) != ge::SUCCESS,
  884. return ge::FAILED, "check optypelist_for_implmode and op_select_implmode failed!");
  885. std::map<string, string> options;
  886. // need to be changed when ge.ini plan is done
  887. SetEnvForSingleOp(options);
  888. auto ret = ge::GELib::Initialize(options);
  889. if (ret != ge::SUCCESS) {
  890. DOMI_LOGE("GE initialize failed!");
  891. return domi::FAILED;
  892. }
  893. ge::GeGenerator generator;
  894. ret = generator.Initialize(options, domi::GetContext());
  895. if (ret != SUCCESS) {
  896. DOMI_LOGE("GeGenerator initialize failed!");
  897. (void)ge::GELib::GetInstance()->Finalize();
  898. return domi::FAILED;
  899. }
  900. vector<ge::SingleOpBuildParam> build_params;
  901. if (ge::SingleOpParser::ParseSingleOpList(json_file_path, build_params) != ge::SUCCESS) {
  902. DOMI_LOGE("parse single op json file failed");
  903. (void)generator.Finalize();
  904. (void)ge::GELib::GetInstance()->Finalize();
  905. return domi::FAILED;
  906. }
  907. int index = 0;
  908. for (auto &param : build_params) {
  909. string output_path;
  910. if (!FLAGS_output.empty()) {
  911. output_path = FLAGS_output + "/";
  912. }
  913. output_path += param.file_name;
  914. ret = generator.BuildSingleOpModel(param.op_desc, param.inputs, param.outputs, output_path);
  915. if (ret != SUCCESS) {
  916. DOMI_LOGE("Compile op failed. ge ret = %u, op index = %d", ret, index);
  917. ret = domi::FAILED;
  918. break;
  919. }
  920. GELOGI("Compile op success. op index = %d, output = %s", index, output_path.c_str());
  921. index += 1;
  922. }
  923. (void)generator.Finalize();
  924. (void)ge::GELib::GetInstance()->Finalize();
  925. return ret;
  926. }
  927. domi::Status GenerateOmModel() {
  928. if (!CheckInputFormat()) {
  929. GELOGE(ge::FAILED, "Check input_format failed");
  930. return domi::FAILED;
  931. }
  932. Status ret = GFlagUtils::CheckFlags();
  933. GE_CHK_BOOL_EXEC(ret == domi::SUCCESS, return domi::FAILED,
  934. "Check flags failed! Please check whether some atc params that include semicolons[;] use double "
  935. "quotation marks (\") to enclose each argument such as out_nodes, input_shape, dynamic_image_size");
  936. #if !defined(__ANDROID__) && !defined(ANDROID)
  937. // Load custom operator Library
  938. LoadCustomOpLib(true);
  939. SaveCustomCaffeProtoPath();
  940. GE_CHK_BOOL_EXEC(ret == domi::SUCCESS, return domi::FAILED, "check custom aicpu run so failed!");
  941. #endif
  942. const int f_stream_num = 1;
  943. std::map<string, string> options;
  944. options.insert(std::pair<string, string>(string(ge::FRAMEWORK_TYPE), to_string(FLAGS_framework)));
  945. options.insert(std::pair<string, string>(string(ge::STREAM_NUM), to_string(f_stream_num)));
  946. options.insert(std::pair<string, string>(string(ge::CALIBRATION_CONF_FILE), FLAGS_cal_conf));
  947. options.insert(std::pair<string, string>(string(ge::ENCRYPT_MODE), to_string(FLAGS_encrypt_mode)));
  948. options.insert(std::pair<string, string>(string(ge::EK_FILE), FLAGS_encrypt_key));
  949. options.insert(std::pair<string, string>(string(ge::CERT_FILE), FLAGS_certificate));
  950. options.insert(std::pair<string, string>(string(ge::HW_KEY_FILE), FLAGS_hardware_key));
  951. options.insert(std::pair<string, string>(string(ge::PRIVATE_KEY_FILE), FLAGS_private_key));
  952. options.insert(std::pair<string, string>(string(ge::OUTPUT_NODE_NAME), FLAGS_out_nodes));
  953. options.insert(std::pair<string, string>(string(ge::INSERT_OP_FILE), FLAGS_insert_op_conf));
  954. options.insert(std::pair<string, string>(string(ge::PRECISION_MODE), FLAGS_precision_mode));
  955. options.insert(std::pair<string, string>(string(ge::RUN_FLAG), to_string(0)));
  956. options.insert(std::pair<string, string>(string(ge::TRAIN_FLAG), to_string(0)));
  957. if (!FLAGS_output_type.empty()) {
  958. options.insert(std::pair<string, string>(string(ge::OUTPUT_DATATYPE), FLAGS_output_type));
  959. }
  960. options.insert(std::pair<string, string>(string(ge::OP_SELECT_IMPL_MODE), FLAGS_op_select_implmode));
  961. options.insert(std::pair<string, string>(string(ge::OPTYPELIST_FOR_IMPLMODE), FLAGS_optypelist_for_implmode));
  962. if (!FLAGS_input_fp16_nodes.empty()) {
  963. GELOGI("FLAGS_input_fp16_nodes : %s .", FLAGS_input_fp16_nodes.c_str());
  964. options.insert(std::pair<string, string>(ge::INPUT_FP16_NODES, FLAGS_input_fp16_nodes));
  965. }
  966. options.insert(std::pair<string, string>(string(ge::AUTO_TUNE_MODE), FLAGS_auto_tune_mode));
  967. options.insert(
  968. std::pair<string, string>(string(ge::OPTION_EXEC_DISABLE_REUSED_MEMORY), to_string(FLAGS_disable_reuse_memory)));
  969. options.insert(std::pair<string, string>(string(ge::SOC_VERSION), FLAGS_soc_version));
  970. options.insert(std::pair<string, string>(string(ge::CORE_TYPE), FLAGS_core_type));
  971. options.insert(std::pair<string, string>(string(ge::AICORE_NUM), FLAGS_aicore_num));
  972. options.insert(std::pair<string, string>(string(ge::BUFFER_OPTIMIZE), FLAGS_buffer_optimize));
  973. options.insert(std::pair<string, string>(string(ge::ENABLE_SMALL_CHANNEL), FLAGS_enable_small_channel));
  974. options.insert(std::pair<string, string>(string(ge::FUSION_SWITCH_FILE), FLAGS_fusion_switch_file));
  975. options.insert(std::pair<string, string>(string(ge::ENABLE_COMPRESS_WEIGHT),
  976. (FLAGS_enable_compress_weight == "true") ?
  977. ge::kEnableCompressWeightTrue : ge::kEnableCompressWeightFalse));
  978. options.insert(std::pair<string, string>(string(ge::GRAPH_MEMORY_MAX_SIZE), kGraphMemoryManagerMallocMaxSize));
  979. options.insert(std::pair<string, string>(string(ge::ENABLE_SINGLE_STREAM), FLAGS_enable_single_stream));
  980. SetDynamicInputSizeOptions();
  981. if (!FLAGS_save_original_model.empty()) {
  982. options.insert(std::pair<string, string>(string(ge::SAVE_ORIGINAL_MODEL), FLAGS_save_original_model));
  983. options.insert(std::pair<string, string>(string(ge::ORIGINAL_MODEL_FILE), FLAGS_output + "_original.om"));
  984. }
  985. options.insert(std::pair<string, string>(string(ge::OP_DEBUG_LEVEL), to_string(FLAGS_op_debug_level)));
  986. // set enable scope fusion passes
  987. SetEnableScopeFusionPasses(FLAGS_enable_scope_fusion_passes);
  988. // print atc option map
  989. ge::PrintOptionMap(options, "atc option");
  990. // When the ATC module is transferred to a model, the suffix ".om" is automatically added to the model name
  991. FLAGS_output = FLAGS_output + ".om";
  992. ret = GenerateModel(options, FLAGS_output);
  993. if (ret != domi::SUCCESS) {
  994. return domi::FAILED;
  995. }
  996. return domi::SUCCESS;
  997. }
  998. domi::Status ConvertModelToJson() {
  999. Status ret = GFlagUtils::CheckConverJsonParamFlags();
  1000. GE_CHK_BOOL_EXEC(ret == domi::SUCCESS, return domi::FAILED, "Check convert json params flags failed!");
  1001. ret = ConvertModelToJson(FLAGS_framework, FLAGS_om, FLAGS_json);
  1002. GE_IF_BOOL_EXEC(ret != domi::SUCCESS, return domi::FAILED);
  1003. return domi::SUCCESS;
  1004. }
  1005. bool CheckRet(domi::Status ret) {
  1006. if (ret != domi::SUCCESS) {
  1007. if (FLAGS_mode == ONLY_PRE_CHECK) {
  1008. GELOGW("ATC precheck failed.");
  1009. } else if (FLAGS_mode == GEN_OM_MODEL) {
  1010. GELOGW("ATC generate offline model failed.");
  1011. } else if (FLAGS_mode == MODEL_TO_JSON) {
  1012. GELOGW("ATC convert model to json file failed.");
  1013. } else if (FLAGS_mode == PBTXT_TO_JSON) {
  1014. GELOGW("ATC convert pbtxt to json file failed.");
  1015. } else {
  1016. return false;
  1017. }
  1018. return false;
  1019. }
  1020. if (FLAGS_mode == ONLY_PRE_CHECK) {
  1021. GELOGI("ATC precheck success.");
  1022. } else if (FLAGS_mode == GEN_OM_MODEL) {
  1023. GELOGI("ATC generate offline model success.");
  1024. } else if (FLAGS_mode == MODEL_TO_JSON) {
  1025. GELOGI("ATC convert model to json file success.");
  1026. } else if (FLAGS_mode == PBTXT_TO_JSON) {
  1027. GELOGI("ATC convert pbtxt to json file success.");
  1028. }
  1029. return true;
  1030. }
  1031. domi::Status ConvertPbtxtToJson() {
  1032. Status ret = GFlagUtils::CheckConverJsonParamFlags();
  1033. if (ret != domi::SUCCESS) {
  1034. GELOGE(ge::FAILED, "Check convert json params flags failed!");
  1035. return domi::FAILED;
  1036. }
  1037. ret = ge::ConvertPbtxtToJson(FLAGS_om.c_str(), FLAGS_json.c_str());
  1038. if (ret != domi::SUCCESS) {
  1039. GELOGE(ge::FAILED, "ConvertPbtxtToJson fail.");
  1040. return domi::FAILED;
  1041. }
  1042. return domi::SUCCESS;
  1043. }
  1044. int init(int argc, char* argv[]) {
  1045. GFlagUtils::InitGFlag(argc, argv);
  1046. // set log level
  1047. int ret = -1;
  1048. const std::set<string> log_level = {"null", "debug", "info", "warning", "error"};
  1049. if (log_level.count(FLAGS_log) == 0) {
  1050. std::cout << "E10010: invalid value for --log:" << FLAGS_log
  1051. <<", only support debug, info, warning, error, null"<< std::endl;
  1052. return ret;
  1053. }
  1054. ret = ge::CheckLogParamValidAndSetLogLevel(FLAGS_log);
  1055. if (ret != 0) {
  1056. return ret;
  1057. }
  1058. std::string path_base = ge::GELib::GetPath();
  1059. ret = ErrorManager::GetInstance().Init(path_base);
  1060. if (ret != 0) {
  1061. DOMI_LOGE("ErrorManager init fail !");
  1062. return ret;
  1063. }
  1064. return 0;
  1065. }
  1066. long GetMemInfo(const std::string &key) {
  1067. std::string file_path = "/proc/meminfo";
  1068. std::ifstream fs(file_path, std::ifstream::in);
  1069. if (!fs.is_open()) {
  1070. GELOGW("Can not open %s .", file_path.c_str());
  1071. return 0;
  1072. }
  1073. std::string line;
  1074. while (getline(fs, line)) { // line not with \n
  1075. if (line.find(key) != std::string::npos) {
  1076. GELOGI("Find mem [%s] info line [%s]", key.c_str(), line.c_str());
  1077. fs.close();
  1078. size_t pos = line.find(":");
  1079. if (pos == std::string::npos) {
  1080. return 0;
  1081. }
  1082. std::string current_mem_info_str = line.substr(pos + 1);
  1083. ge::StringUtils::Trim(current_mem_info_str);
  1084. GELOGI("Find mem [%s] info [%s].", key.c_str(), current_mem_info_str.c_str());
  1085. return stol(current_mem_info_str);
  1086. }
  1087. }
  1088. fs.close(); // close the file
  1089. return 0;
  1090. }
  1091. bool CheckMemInfo() {
  1092. if (FLAGS_auto_tune_mode.empty()) {
  1093. return true;
  1094. }
  1095. // only check current available mem when auto_tune_mode is set.
  1096. long current_mem_available = GetMemInfo("MemAvailable");
  1097. GELOGI("Get mem available [%lu].", current_mem_available);
  1098. std::cout << "Current available mem is " << current_mem_available << "kB." << std::endl;
  1099. if ((current_mem_available > 0) && (current_mem_available < kMinAvailableMem)) {
  1100. GELOGE(ge::PARAM_INVALID, "Current available mem [%lu] can not be smaller than [%lu] .",
  1101. current_mem_available, kMinAvailableMem);
  1102. ErrorManager::GetInstance().ATCReportErrMessage("E10044", {"value", "min_value"},
  1103. {to_string(current_mem_available), to_string(kMinAvailableMem)});
  1104. return false;
  1105. }
  1106. return true;
  1107. }
  1108. int main(int argc, char* argv[]) {
  1109. Status ret = domi::SUCCESS;
  1110. std::cout << "ATC start working now, please wait for a moment." << std::endl;
  1111. // Initialize
  1112. if (init(argc, argv) != 0) {
  1113. std::cout << "ATC run failed, Please check the detail log, Try \'atc --help\' for more information" << std::endl;
  1114. return -1;
  1115. }
  1116. do {
  1117. if (!CheckMemInfo()) {
  1118. GELOGE(ge::PARAM_INVALID, "Current available mem is too small");
  1119. ret = domi::FAILED;
  1120. break;
  1121. }
  1122. if (!FLAGS_singleop.empty()) {
  1123. ret = GenerateSingleOp(FLAGS_singleop);
  1124. break;
  1125. }
  1126. // default mode(mode:0), Open source model to model
  1127. if (GEN_OM_MODEL == FLAGS_mode || ONLY_PRE_CHECK == FLAGS_mode) {
  1128. GE_IF_BOOL_EXEC(GenerateOmModel() != domi::SUCCESS, ret = domi::FAILED; break);
  1129. } else if (MODEL_TO_JSON == FLAGS_mode) { // Mode 1, transfer model to JSON
  1130. GE_CHK_BOOL_EXEC(ConvertModelToJson() == domi::SUCCESS, ret = domi::FAILED;
  1131. break, "ATC ConvertJson execute failed!!");
  1132. } else if (FLAGS_mode == ge::RunMode::PBTXT_TO_JSON) {
  1133. GE_CHK_BOOL_EXEC(ConvertPbtxtToJson() == domi::SUCCESS, ret = domi::FAILED;
  1134. break, "ATC convert pbtxt to json execute failed!!");
  1135. } else {
  1136. ErrorManager::GetInstance().ATCReportErrMessage(
  1137. "E10001", {"parameter", "value", "reason"}, {"--mode", std::to_string(FLAGS_mode), kModeSupport});
  1138. GELOGE(ge::PARAM_INVALID, "Invalid value for --mode[%d], %s.", FLAGS_mode, kModeSupport);
  1139. ret = domi::FAILED;
  1140. break;
  1141. }
  1142. } while (0);
  1143. if (!CheckRet(ret)) {
  1144. std::cout << "ATC run failed, Please check the detail log, Try \'atc --help\' for more information" << std::endl;
  1145. int result = ErrorManager::GetInstance().OutputErrMessage(STDOUT_FILENO);
  1146. if (result != 0) {
  1147. DOMI_LOGE("ErrorManager outputErrMessage fail !");
  1148. }
  1149. GELOGI("Current mem available mem is [%lu]", GetMemInfo("MemAvailable"));
  1150. return ret;
  1151. } else {
  1152. std::cout << "ATC run success, welcome to the next use." << std::endl;
  1153. (void)ErrorManager::GetInstance().OutputMessage(STDOUT_FILENO);
  1154. return 0;
  1155. }
  1156. } /*lint +e530*/

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