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.

network.cpp 18 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. /**
  2. * \file src/network.cpp
  3. * MegEngine is Licensed under the Apache License, Version 2.0 (the "License")
  4. *
  5. * Copyright (c) 2014-2021 Megvii Inc. All rights reserved.
  6. *
  7. * Unless required by applicable law or agreed to in writing,
  8. * software distributed under the License is distributed on an
  9. * "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. */
  11. #include "lite/network.h"
  12. #include "function_base.h"
  13. #include "network_impl_base.h"
  14. #include "parse_info/parse_info_base.h"
  15. #include "parse_model/model_parser.h"
  16. #include "type_info.h"
  17. #if LITE_BUILD_WITH_MGE
  18. #include "mge/function_dft.h"
  19. #include "mge/network_impl.h"
  20. #endif
  21. #include <fstream>
  22. #include <memory>
  23. using namespace lite;
  24. /**
  25. * \brief Construct the new work implement
  26. * the order must be :
  27. * 1. creeat the implement
  28. * 2. config and load
  29. * 3. set_io
  30. */
  31. Network::Network(const Config& config, const NetworkIO& network_io) {
  32. LITE_ERROR_HANDLER_BEGIN
  33. m_config = config;
  34. m_network_io = network_io;
  35. if (config.backend == LiteBackend::LITE_DEFAULT) {
  36. m_impl = call_func<NetworkImplDft,
  37. std::unique_ptr<lite::Network::NetworkImplBase>>(
  38. "create_network");
  39. }
  40. m_impl->set_config(config);
  41. m_impl->set_io(network_io);
  42. LITE_ERROR_HANDLER_END
  43. }
  44. Network::Network(const NetworkIO& network_io, const Config& config) {
  45. LITE_ERROR_HANDLER_BEGIN
  46. m_config = config;
  47. m_network_io = network_io;
  48. if (config.backend == LiteBackend::LITE_DEFAULT) {
  49. m_impl = call_func<NetworkImplDft,
  50. std::unique_ptr<lite::Network::NetworkImplBase>>(
  51. "create_network");
  52. }
  53. m_impl->set_config(config);
  54. m_impl->set_io(network_io);
  55. LITE_ERROR_HANDLER_END
  56. }
  57. void Network::load_model(void* model_mem, size_t size) {
  58. LITE_ERROR_HANDLER_BEGIN
  59. LITE_CHECK_NON_NULL_POINTER(m_impl);
  60. //! this model_mem is managed by user
  61. std::shared_ptr<void> model{model_mem, [](void*) {}};
  62. prase_model(model, size);
  63. LITE_ERROR_HANDLER_END
  64. }
  65. void Network::load_model(std::string model_path) {
  66. LITE_ERROR_HANDLER_BEGIN
  67. LITE_CHECK_NON_NULL_POINTER(m_impl);
  68. FILE* fin = fopen(model_path.c_str(), "rb");
  69. LITE_ASSERT(fin, "failed to open %s: %s", model_path.c_str(),
  70. strerror(errno));
  71. fseek(fin, 0, SEEK_END);
  72. size_t size = ftell(fin);
  73. fseek(fin, 0, SEEK_SET);
  74. void* ptr = malloc(size);
  75. std::shared_ptr<void> buf{ptr, ::free};
  76. auto nr = fread(buf.get(), 1, size, fin);
  77. LITE_ASSERT(nr == size);
  78. fclose(fin);
  79. prase_model(buf, size);
  80. LITE_ERROR_HANDLER_END
  81. }
  82. void Network::prase_model(std::shared_ptr<void> model_data, size_t size) {
  83. std::unordered_map<std::string, LiteAny> separate_config_map;
  84. ModelParser model_parser(model_data, size);
  85. //! parse the model info
  86. if (model_parser.parse_model_info(m_config, m_network_io,
  87. separate_config_map, m_extra_info)) {
  88. if (m_config.backend == LiteBackend::LITE_DEFAULT &&
  89. m_impl->get_backend_type() != LiteBackend::LITE_DEFAULT) {
  90. m_impl.reset(try_call_func<NetworkImplDft,
  91. lite::Network::NetworkImplBase*>(
  92. "parse_model"));
  93. }
  94. m_impl->set_config(m_config);
  95. m_impl->set_io(m_network_io);
  96. }
  97. //! decryption the model
  98. size_t model_length;
  99. auto&& model_shared_ptr = model_parser.parse_model(model_length, m_config);
  100. m_impl->load_model(model_shared_ptr, model_length, separate_config_map);
  101. m_loaded = true;
  102. update_from_implement();
  103. }
  104. Network::~Network() = default;
  105. void Network::update_from_implement() {
  106. m_config.device_type = m_impl->get_device_type();
  107. }
  108. void Network::compute_only_configured_output() {
  109. LITE_ERROR_HANDLER_BEGIN
  110. LITE_ASSERT(!m_loaded,
  111. "compute_only_configured_output should be used before model "
  112. "loaded.");
  113. LITE_CHECK_NON_NULL_POINTER(m_impl);
  114. return m_impl->compute_only_configured_output();
  115. LITE_ERROR_HANDLER_END
  116. }
  117. std::shared_ptr<Tensor> Network::get_io_tensor(std::string name,
  118. LiteTensorPhase phase) {
  119. LITE_ERROR_HANDLER_BEGIN
  120. LITE_ASSERT(m_loaded, "get_io_tensor should be used after model loaded.");
  121. LITE_CHECK_NON_NULL_POINTER(m_impl);
  122. return m_impl->get_io_tensor(name, phase);
  123. LITE_ERROR_HANDLER_END
  124. }
  125. std::shared_ptr<Tensor> Network::get_input_tensor(size_t index) {
  126. LITE_ERROR_HANDLER_BEGIN
  127. LITE_ASSERT(m_loaded,
  128. "get_input_tensor should be used after model loaded.");
  129. LITE_CHECK_NON_NULL_POINTER(m_impl);
  130. return m_impl->get_input_tensor(index);
  131. LITE_ERROR_HANDLER_END
  132. }
  133. std::shared_ptr<Tensor> Network::get_output_tensor(size_t index) {
  134. LITE_ERROR_HANDLER_BEGIN
  135. LITE_ASSERT(m_loaded,
  136. "get_output_tensor should be used after model loaded.");
  137. LITE_CHECK_NON_NULL_POINTER(m_impl);
  138. return m_impl->get_output_tensor(index);
  139. LITE_ERROR_HANDLER_END
  140. }
  141. Network& Network::set_async_callback(const AsyncCallback& callback) {
  142. LITE_ERROR_HANDLER_BEGIN
  143. LITE_CHECK_NON_NULL_POINTER(m_impl);
  144. m_impl->set_async_callback(std::move(callback));
  145. return *this;
  146. LITE_ERROR_HANDLER_END
  147. }
  148. Network& Network::set_start_callback(const StartCallback& callback) {
  149. LITE_ERROR_HANDLER_BEGIN
  150. LITE_CHECK_NON_NULL_POINTER(m_impl);
  151. m_impl->set_start_callback(std::move(callback));
  152. return *this;
  153. LITE_ERROR_HANDLER_END
  154. }
  155. Network& Network::set_finish_callback(const FinishCallback& callback) {
  156. LITE_ERROR_HANDLER_BEGIN
  157. LITE_CHECK_NON_NULL_POINTER(m_impl);
  158. m_impl->set_finish_callback(std::move(callback));
  159. return *this;
  160. LITE_ERROR_HANDLER_END
  161. }
  162. Network& Network::set_device_id(int device_id) {
  163. LITE_ERROR_HANDLER_BEGIN
  164. LITE_ASSERT(!m_loaded, "set_device_id should be used before model loaded.");
  165. LITE_CHECK_NON_NULL_POINTER(m_impl);
  166. m_impl->set_device_id(device_id);
  167. return *this;
  168. LITE_ERROR_HANDLER_END
  169. }
  170. Network& Network::set_stream_id(int stream_id) {
  171. LITE_ERROR_HANDLER_BEGIN
  172. LITE_ASSERT(!m_loaded, "set_stream_id should be used before model loaded.");
  173. LITE_CHECK_NON_NULL_POINTER(m_impl);
  174. m_impl->set_stream_id(stream_id);
  175. return *this;
  176. LITE_ERROR_HANDLER_END
  177. }
  178. void Network::forward() {
  179. LITE_ERROR_HANDLER_BEGIN
  180. LITE_ASSERT(m_loaded, "forward should be used after model loaded.");
  181. LITE_CHECK_NON_NULL_POINTER(m_impl.get());
  182. m_impl->forward();
  183. LITE_ERROR_HANDLER_END
  184. }
  185. void Network::wait() {
  186. LITE_ERROR_HANDLER_BEGIN
  187. LITE_ASSERT(m_loaded, "wait should be used after model loaded.");
  188. LITE_CHECK_NON_NULL_POINTER(m_impl);
  189. m_impl->wait();
  190. LITE_ERROR_HANDLER_END
  191. }
  192. std::string Network::get_input_name(size_t index) const {
  193. LITE_ERROR_HANDLER_BEGIN
  194. LITE_ASSERT(m_loaded, "get_input_name should be used after model loaded.");
  195. LITE_CHECK_NON_NULL_POINTER(m_impl);
  196. return m_impl->get_input_name(index);
  197. LITE_ERROR_HANDLER_END
  198. }
  199. std::string Network::get_output_name(size_t index) const {
  200. LITE_ERROR_HANDLER_BEGIN
  201. LITE_ASSERT(m_loaded, "get_output_name should be used after model loaded.");
  202. LITE_CHECK_NON_NULL_POINTER(m_impl);
  203. return m_impl->get_output_name(index);
  204. LITE_ERROR_HANDLER_END
  205. }
  206. std::vector<std::string> Network::get_all_input_name() const {
  207. LITE_ERROR_HANDLER_BEGIN
  208. LITE_ASSERT(m_loaded,
  209. "get_all_input_name should be used after model loaded.");
  210. LITE_CHECK_NON_NULL_POINTER(m_impl);
  211. auto all_input_name = m_impl->get_all_input_name();
  212. std::vector<std::string> all_names;
  213. for (auto& name : all_input_name) {
  214. all_names.push_back(name);
  215. }
  216. return all_names;
  217. LITE_ERROR_HANDLER_END
  218. }
  219. std::vector<std::string> Network::get_all_output_name() const {
  220. LITE_ERROR_HANDLER_BEGIN
  221. LITE_ASSERT(m_loaded,
  222. "get_all_output_name should be used after model loaded.");
  223. LITE_CHECK_NON_NULL_POINTER(m_impl);
  224. auto all_output_name = m_impl->get_all_output_name();
  225. std::vector<std::string> all_names;
  226. for (auto& name : all_output_name) {
  227. all_names.push_back(name);
  228. }
  229. return all_names;
  230. LITE_ERROR_HANDLER_END
  231. }
  232. int Network::get_device_id() const {
  233. LITE_ERROR_HANDLER_BEGIN
  234. LITE_CHECK_NON_NULL_POINTER(m_impl);
  235. return m_impl->get_device_id();
  236. LITE_ERROR_HANDLER_END
  237. }
  238. int Network::get_stream_id() const {
  239. LITE_ERROR_HANDLER_BEGIN
  240. LITE_CHECK_NON_NULL_POINTER(m_impl);
  241. return m_impl->get_stream_id();
  242. LITE_ERROR_HANDLER_END
  243. }
  244. void Network::enable_profile_performance(std::string profile_file_path) {
  245. LITE_ERROR_HANDLER_BEGIN
  246. m_impl->enable_profile_performance(profile_file_path);
  247. LITE_ERROR_HANDLER_END
  248. }
  249. const std::string& Network::get_model_extra_info() {
  250. LITE_ERROR_HANDLER_BEGIN
  251. return m_extra_info;
  252. LITE_ERROR_HANDLER_END
  253. }
  254. LiteDeviceType Network::get_device_type() const {
  255. LITE_ERROR_HANDLER_BEGIN
  256. return m_impl->get_device_type();
  257. LITE_ERROR_HANDLER_END
  258. }
  259. /*********************** MGE special network function ***************/
  260. void Runtime::set_cpu_threads_number(std::shared_ptr<Network> network,
  261. size_t nr_threads) {
  262. LITE_ERROR_HANDLER_BEGIN
  263. auto network_impl = NetworkHelper::implement(network);
  264. if (network_impl->get_backend_type() == LiteBackend::LITE_DEFAULT) {
  265. LITE_ASSERT(
  266. !NetworkHelper::loaded(network),
  267. "set_cpu_threads_number should be used before model loaded.");
  268. call_func<NetworkImplDft, void>("set_cpu_threads_number", network_impl,
  269. nr_threads);
  270. return;
  271. }
  272. LITE_THROW("set_cpu_threads_number is not aviliable in the backend.");
  273. LITE_ERROR_HANDLER_END
  274. }
  275. void Runtime::use_tensorrt(std::shared_ptr<Network> network) {
  276. LITE_ERROR_HANDLER_BEGIN
  277. auto network_impl = NetworkHelper::implement(network);
  278. if (network_impl->get_backend_type() == LiteBackend::LITE_DEFAULT) {
  279. LITE_ASSERT(!NetworkHelper::loaded(network),
  280. "use_tensorrt should be used before model loaded.");
  281. call_func<NetworkImplDft, void>("use_tensorrt", network_impl);
  282. return;
  283. }
  284. LITE_THROW("use_tensorrt is not aviliable in the backend.");
  285. LITE_ERROR_HANDLER_END
  286. }
  287. size_t Runtime::get_cpu_threads_number(const std::shared_ptr<Network> network) {
  288. LITE_ERROR_HANDLER_BEGIN
  289. auto network_impl = NetworkHelper::implement(network);
  290. if (network_impl->get_backend_type() == LiteBackend::LITE_DEFAULT) {
  291. return call_func<NetworkImplDft, size_t>("get_cpu_threads_number",
  292. network_impl);
  293. }
  294. LITE_THROW("get_cpu_threads_number is not aviliable in the backend.");
  295. LITE_ERROR_HANDLER_END
  296. }
  297. void Runtime::set_runtime_thread_affinity(
  298. std::shared_ptr<Network> network,
  299. const ThreadAffinityCallback& thread_affinity_callback) {
  300. LITE_ERROR_HANDLER_BEGIN
  301. auto network_impl = NetworkHelper::implement(network);
  302. if (network_impl->get_backend_type() == LiteBackend::LITE_DEFAULT) {
  303. LITE_ASSERT(NetworkHelper::loaded(network),
  304. "set_runtime_thread_affinity should be used after model "
  305. "loaded.");
  306. call_func<NetworkImplDft, void>("set_runtime_thread_affinity",
  307. network_impl, thread_affinity_callback);
  308. return;
  309. }
  310. LITE_THROW("set_runtime_thread_affinity is not aviliable in the backend.");
  311. LITE_ERROR_HANDLER_END
  312. }
  313. void Runtime::set_cpu_inplace_mode(std::shared_ptr<Network> network) {
  314. LITE_ERROR_HANDLER_BEGIN
  315. auto network_impl = NetworkHelper::implement(network);
  316. if (network_impl->get_backend_type() == LiteBackend::LITE_DEFAULT) {
  317. LITE_ASSERT(!NetworkHelper::loaded(network),
  318. "set_cpu_inplace_mode should be used before model loaded.");
  319. call_func<NetworkImplDft, void>("set_cpu_inplace_mode", network_impl);
  320. return;
  321. }
  322. LITE_THROW("set_cpu_inplace_mode is not aviliable in the backend.");
  323. LITE_ERROR_HANDLER_END
  324. }
  325. bool Runtime::is_cpu_inplace_mode(const std::shared_ptr<Network> network) {
  326. LITE_ERROR_HANDLER_BEGIN
  327. auto network_impl = NetworkHelper::implement(network);
  328. if (network_impl->get_backend_type() == LiteBackend::LITE_DEFAULT) {
  329. return call_func<NetworkImplDft, bool>("is_cpu_inplace_mode",
  330. network_impl);
  331. }
  332. LITE_THROW("is_cpu_inplace_mode is not aviliable in the backend.");
  333. LITE_ERROR_HANDLER_END
  334. }
  335. //! set opr algorithm selection strategy in the network
  336. void Runtime::set_network_algo_policy(std::shared_ptr<Network> network,
  337. LiteAlgoSelectStrategy strategy,
  338. uint32_t shared_batch_size,
  339. bool binary_equal_between_batch) {
  340. LITE_ERROR_HANDLER_BEGIN
  341. auto network_impl = NetworkHelper::implement(network);
  342. if (network_impl->get_backend_type() == LiteBackend::LITE_DEFAULT) {
  343. call_func<NetworkImplDft, void>("set_network_algo_policy", network_impl,
  344. strategy, shared_batch_size,
  345. binary_equal_between_batch);
  346. return;
  347. }
  348. LITE_THROW("set_network_algo_policy is not aviliable in the backend.");
  349. LITE_ERROR_HANDLER_END
  350. }
  351. //! set opr algorithm selection strategy in the network
  352. void Runtime::set_network_algo_workspace_limit(std::shared_ptr<Network> network,
  353. size_t workspace_limit) {
  354. LITE_ERROR_HANDLER_BEGIN
  355. auto network_impl = NetworkHelper::implement(network);
  356. if (network_impl->get_backend_type() == LiteBackend::LITE_DEFAULT) {
  357. LITE_ASSERT(NetworkHelper::loaded(network),
  358. "set_network_algo_policy should be used after model "
  359. "loaded.");
  360. call_func<NetworkImplDft, void>("set_network_algo_workspace_limit",
  361. network_impl, workspace_limit);
  362. return;
  363. }
  364. LITE_THROW(
  365. "set_network_algo_workspace_limit is not aviliable in the "
  366. "backend.");
  367. LITE_ERROR_HANDLER_END
  368. }
  369. //! set the network memroy allocator, the allocator is defined by user
  370. void Runtime::set_memory_allocator(std::shared_ptr<Network> network,
  371. std::shared_ptr<Allocator> user_allocator) {
  372. LITE_ERROR_HANDLER_BEGIN
  373. auto network_impl = NetworkHelper::implement(network);
  374. if (network_impl->get_backend_type() == LiteBackend::LITE_DEFAULT) {
  375. LITE_ASSERT(!NetworkHelper::loaded(network),
  376. "set_memory_allocator should be used before model loaded.");
  377. call_func<NetworkImplDft, void>("set_memory_allocator", network_impl,
  378. user_allocator);
  379. return;
  380. }
  381. LITE_THROW("set_memory_allocator is not aviliable in the backend.");
  382. LITE_ERROR_HANDLER_END
  383. }
  384. void Runtime::share_runtime_memory_with(std::shared_ptr<Network> dst_network,
  385. std::shared_ptr<Network> src_network) {
  386. LITE_ERROR_HANDLER_BEGIN
  387. auto network_impl_dst = NetworkHelper::implement(dst_network);
  388. if (network_impl_dst->get_backend_type() == LiteBackend::LITE_DEFAULT) {
  389. LITE_ASSERT(!NetworkHelper::loaded(dst_network),
  390. "share_runtime_memory_with should be used before model "
  391. "loaded.");
  392. call_func<NetworkImplDft, void>("share_runtime_memory_with",
  393. network_impl_dst,
  394. NetworkHelper::implement(src_network));
  395. return;
  396. }
  397. LITE_THROW("share_runtime_memory_with is not aviliable in the backend.");
  398. LITE_ERROR_HANDLER_END
  399. }
  400. void Runtime::enable_io_txt_dump(std::shared_ptr<Network> network,
  401. std::string io_txt_out_file) {
  402. LITE_ERROR_HANDLER_BEGIN
  403. auto network_impl = NetworkHelper::implement(network);
  404. if (network_impl->get_backend_type() == LiteBackend::LITE_DEFAULT) {
  405. call_func<NetworkImplDft, void>("enable_io_txt_dump", network_impl,
  406. io_txt_out_file);
  407. return;
  408. }
  409. LITE_THROW("enable_io_txt_dump is not aviliable in the backend.");
  410. LITE_ERROR_HANDLER_END
  411. }
  412. void Runtime::enable_io_bin_dump(std::shared_ptr<Network> network,
  413. std::string io_bin_out_dir) {
  414. LITE_ERROR_HANDLER_BEGIN
  415. auto network_impl = NetworkHelper::implement(network);
  416. if (network_impl->get_backend_type() == LiteBackend::LITE_DEFAULT) {
  417. call_func<NetworkImplDft, void>("enable_io_bin_dump", network_impl,
  418. io_bin_out_dir);
  419. return;
  420. }
  421. LITE_THROW("enable_io_bin_dump is not aviliable in the backend.");
  422. LITE_ERROR_HANDLER_END
  423. }
  424. void Runtime::shared_weight_with_network(
  425. std::shared_ptr<Network> dst_network,
  426. const std::shared_ptr<Network> src_network) {
  427. LITE_ERROR_HANDLER_BEGIN
  428. auto network_impl_dst = NetworkHelper::implement(dst_network);
  429. if (network_impl_dst->get_backend_type() == LiteBackend::LITE_DEFAULT) {
  430. LITE_ASSERT(NetworkHelper::loaded(src_network),
  431. "shared_weight_with_network should be used after the src "
  432. "network "
  433. "loaded.");
  434. auto src_implment = NetworkHelper::implement(src_network);
  435. call_func<NetworkImplDft, void>("shared_weight_with", network_impl_dst,
  436. src_implment);
  437. NetworkHelper::loaded(dst_network, true);
  438. return;
  439. }
  440. LITE_THROW("shared_weight_with_network is not aviliable in the backend.");
  441. LITE_ERROR_HANDLER_END
  442. }
  443. // vim: syntax=cpp.doxygen foldmethod=marker foldmarker=f{{{,f}}}

MegEngine 安装包中集成了使用 GPU 运行代码所需的 CUDA 环境,不用区分 CPU 和 GPU 版。 如果想要运行 GPU 程序,请确保机器本身配有 GPU 硬件设备并安装好驱动。 如果你想体验在云端 GPU 算力平台进行深度学习开发的感觉,欢迎访问 MegStudio 平台