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.

test_network_c.cpp 30 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863
  1. /**
  2. * \file test/test_network_c.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 "../src/misc.h"
  12. #if LITE_BUILD_WITH_MGE
  13. #include "../src/common.h"
  14. #include "../src/mge/network_impl.h"
  15. #include "../lite-c/src/common.h"
  16. #include "lite-c/global_c.h"
  17. #include "lite-c/network_c.h"
  18. #include "lite-c/tensor_c.h"
  19. #include "./test_common.h"
  20. #include "megbrain/tensor.h"
  21. #include <string.h>
  22. #include <chrono>
  23. #include <memory>
  24. #include <random>
  25. #include <unordered_map>
  26. namespace {
  27. int affinity_set = false;
  28. int single_thread_affinity(int) {
  29. affinity_set = true;
  30. return 0;
  31. }
  32. std::atomic_size_t m_nr_left{0};
  33. std::atomic_size_t m_nr_allocated{0};
  34. void* allocate(LiteDeviceType device, int, size_t size, size_t align) {
  35. LITE_ASSERT(device == LiteDeviceType::LITE_CPU);
  36. m_nr_left++;
  37. m_nr_allocated++;
  38. #ifdef WIN32
  39. return _aligned_malloc(size, align);
  40. #elif defined(__ANDROID__) || defined(ANDROID)
  41. return memalign(align, size);
  42. #else
  43. void* ptr = nullptr;
  44. auto err = posix_memalign(&ptr, align, size);
  45. mgb_assert(!err, "failed to malloc %zu bytes with align %zu", size, align);
  46. return ptr;
  47. #endif
  48. }
  49. void free(LiteDeviceType device, int, void* ptr) {
  50. m_nr_left--;
  51. LITE_ASSERT(device == LiteDeviceType::LITE_CPU);
  52. #ifdef WIN32
  53. _aligned_free(ptr);
  54. #else
  55. ::free(ptr);
  56. #endif
  57. };
  58. #define NUMBER_THREDS (4)
  59. std::vector<std::thread::id> thread_ids(NUMBER_THREDS);
  60. int multi_thread_affinity(int id) {
  61. thread_ids[id] = std::this_thread::get_id();
  62. return 0;
  63. };
  64. volatile bool finished = false;
  65. int finish_callback() {
  66. finished = true;
  67. return 0;
  68. }
  69. volatile bool start_checked = false;
  70. int start_callback(const LiteIO* inputs, const LiteTensor* input_tensors, size_t size) {
  71. start_checked = true;
  72. auto check_func = [&]() {
  73. ASSERT_EQ(size, 1);
  74. ASSERT_EQ(std::string(inputs->name), "data");
  75. LiteLayout layout;
  76. LITE_get_tensor_layout(*input_tensors, &layout);
  77. ASSERT_EQ(layout.ndim, 4);
  78. ASSERT_EQ(layout.shapes[1], 3);
  79. ASSERT_EQ(layout.shapes[2], 224);
  80. ASSERT_EQ(layout.shapes[3], 224);
  81. };
  82. check_func();
  83. return 0;
  84. }
  85. volatile bool finish_checked = false;
  86. int finish_callback(
  87. const LiteIO* outputs, const LiteTensor* output_tensors, size_t size) {
  88. finish_checked = true;
  89. auto check_func = [&]() {
  90. ASSERT_EQ(size, 1);
  91. ASSERT_EQ(
  92. std::string(outputs->name),
  93. "TRUE_DIV(EXP[12065],reduce0[12067])[12077]");
  94. LiteLayout layout;
  95. LITE_get_tensor_layout(*output_tensors, &layout);
  96. ASSERT_EQ(layout.shapes[1], 1000);
  97. };
  98. check_func();
  99. return 0;
  100. }
  101. } // namespace
  102. #define LITE_CAPI_CHECK(_expr) \
  103. do { \
  104. int _ret = (_expr); \
  105. if (_ret) { \
  106. LITE_THROW(LITE_get_last_error()); \
  107. } \
  108. } while (0)
  109. #define ForwardMgb \
  110. lite::Config config; \
  111. auto lite_tensor = lite::get_input_data("./input_data.npy"); \
  112. size_t data_length_in_byte = lite_tensor->get_tensor_total_size_in_byte(); \
  113. std::string model_path = "./shufflenet.mge"; \
  114. auto result_mgb = mgb_lar(model_path, config, "data", lite_tensor)
  115. #define MakeNetwork \
  116. LiteNetwork c_network; \
  117. LITE_CAPI_CHECK( \
  118. LITE_make_network(&c_network, *default_config(), *default_network_io()))
  119. #define LoadNetwork \
  120. LITE_CAPI_CHECK(LITE_load_model_from_path(c_network, model_path.c_str()))
  121. #define SetInput \
  122. LiteTensor c_input_tensor, c_output_tensor; \
  123. LITE_CAPI_CHECK( \
  124. LITE_get_io_tensor(c_network, "data", LITE_INPUT, &c_input_tensor)); \
  125. LITE_CAPI_CHECK(LITE_reset_tensor_memory( \
  126. c_input_tensor, lite_tensor->get_memory_ptr(), data_length_in_byte))
  127. #define ForwardNetwork \
  128. LITE_CAPI_CHECK(LITE_forward(c_network)); \
  129. LITE_CAPI_CHECK(LITE_wait(c_network))
  130. #define GetOutput \
  131. const char* output_name; \
  132. LITE_CAPI_CHECK(LITE_get_output_name(c_network, 0, &output_name)); \
  133. LITE_CAPI_CHECK(LITE_get_io_tensor( \
  134. c_network, output_name, LITE_OUTPUT, &c_output_tensor)); \
  135. void* output_ptr; \
  136. LITE_CAPI_CHECK(LITE_get_tensor_memory(c_output_tensor, &output_ptr))
  137. #define CompareResult \
  138. EXPECT_TRUE(lite::compare_memory<float>( \
  139. output_ptr, result_mgb->get_memory_ptr(), \
  140. result_mgb->get_tensor_total_size_in_byte() / sizeof(float)))
  141. TEST(TestCapiNetWork, BasicResetInput) {
  142. ForwardMgb;
  143. LiteNetwork c_network;
  144. LITE_CAPI_CHECK(LITE_make_default_network(&c_network));
  145. LoadNetwork;
  146. SetInput;
  147. ForwardNetwork;
  148. GetOutput;
  149. CompareResult;
  150. LITE_destroy_network(c_network);
  151. }
  152. TEST(TestCapiNetWork, GetAllName) {
  153. std::string model_path = "./shufflenet.mge";
  154. LiteNetwork c_network;
  155. LITE_CAPI_CHECK(LITE_make_default_network(&c_network));
  156. LoadNetwork;
  157. size_t input_size, output_size;
  158. LITE_get_all_input_name(c_network, &input_size, nullptr);
  159. LITE_get_all_output_name(c_network, &output_size, nullptr);
  160. std::vector<const char*> input_names(input_size);
  161. LITE_get_all_input_name(c_network, nullptr, input_names.data());
  162. ASSERT_EQ(input_names.size(), 1);
  163. ASSERT_TRUE(std::string(input_names[0]) == "data");
  164. std::vector<const char*> output_names(output_size);
  165. LITE_get_all_output_name(c_network, nullptr, output_names.data());
  166. ASSERT_TRUE(
  167. std::string(output_names[0]) ==
  168. "TRUE_DIV(EXP[12065],reduce0[12067])[12077]");
  169. ASSERT_EQ(output_names.size(), 1);
  170. LITE_destroy_network(c_network);
  171. }
  172. #if LITE_BUILD_WITH_RKNPU
  173. static int GetTop(
  174. float* pfProb, float* pfMaxProb, uint32_t* pMaxClass, uint32_t outputCount,
  175. uint32_t topNum) {
  176. uint32_t i, j;
  177. #define MAX_TOP_NUM 20
  178. if (topNum > MAX_TOP_NUM)
  179. return 0;
  180. memset(pfMaxProb, 0, sizeof(float) * topNum);
  181. memset(pMaxClass, 0xff, sizeof(float) * topNum);
  182. for (j = 0; j < topNum; j++) {
  183. for (i = 0; i < outputCount; i++) {
  184. if ((i == *(pMaxClass + 0)) || (i == *(pMaxClass + 1)) ||
  185. (i == *(pMaxClass + 2)) || (i == *(pMaxClass + 3)) ||
  186. (i == *(pMaxClass + 4))) {
  187. continue;
  188. }
  189. if (pfProb[i] > *(pfMaxProb + j)) {
  190. *(pfMaxProb + j) = pfProb[i];
  191. *(pMaxClass + j) = i;
  192. }
  193. }
  194. }
  195. return 1;
  196. }
  197. TEST(TestCapiNetWork, rknntest_set_info) {
  198. #define SET_INFO_SIZE 2
  199. #define TENSOR_TYPE_UINT8 3
  200. #define TENSOR_FORMAT_NHWC 1
  201. LiteConfig config;
  202. config.backend = LiteBackend::LITE_RK_NPU;
  203. config.device_type = LiteDeviceType::LITE_NPU;
  204. config.bare_model_cryption_name = nullptr;
  205. auto lite_tensor = lite::get_input_data("./model/cat_224x224.npy");
  206. auto true_tensor = lite::get_input_data("./output_data.npy");
  207. auto rknn_model = "./model/mobilenet_v1.rknn";
  208. LiteNetwork c_network;
  209. LITE_CAPI_CHECK(LITE_make_network_config(&c_network, config));
  210. LITE_CAPI_CHECK(LITE_load_model_from_path(c_network, rknn_model));
  211. size_t input_size, output_size;
  212. LITE_get_all_input_name(c_network, &input_size, nullptr);
  213. LITE_get_all_output_name(c_network, &output_size, nullptr);
  214. std::vector<const char*> input_names(input_size);
  215. std::vector<const char*> output_names(output_size);
  216. LiteTensor c_input_tensor, c_output_tensor;
  217. LITE_get_all_input_name(c_network, nullptr, input_names.data());
  218. LITE_get_all_output_name(c_network, nullptr, output_names.data());
  219. LITE_CAPI_CHECK(
  220. LITE_get_io_tensor(c_network, input_names[0], LITE_IO, &c_input_tensor));
  221. size_t input_length = 0;
  222. LITE_get_tensor_total_size_in_byte(c_input_tensor, &input_length);
  223. size_t data_length_in_byte = lite_tensor->get_tensor_total_size_in_byte();
  224. {
  225. LiteLayout input_layout;
  226. LITE_get_tensor_layout(c_input_tensor, &input_layout);
  227. ASSERT_TRUE(input_layout.data_type == LITE_INT8);
  228. std::vector<int> input_shape = {1, 224, 224, 3};
  229. for (size_t i = 0; i < input_layout.ndim; i++) {
  230. ASSERT_TRUE(input_layout.shapes[i] = input_shape[i]);
  231. }
  232. }
  233. {
  234. int size_attr = 0;
  235. LITE_CAPI_CHECK(LITE_get_tensor_attribute(
  236. c_input_tensor, nullptr, nullptr, &size_attr));
  237. ASSERT_TRUE(size_attr > 0);
  238. const char* keys[size_attr];
  239. void* values[size_attr];
  240. LITE_CAPI_CHECK(
  241. LITE_get_tensor_attribute(c_input_tensor, keys, values, &size_attr));
  242. ASSERT_TRUE(size_attr > 5);
  243. std::unordered_map<std::string, uint32_t> result_map = {
  244. {"zp", 0}, {"index", 0}, {"size_with_stride", 150528},
  245. {"stride", 224}, {"n_size", 150528}, {"n_elems", 150528},
  246. {"qnt_type", 2}, {"n_dims", 4}, {"type", 2},
  247. {"fmt", 1}, {"dims0", 1}, {"dims1", 224},
  248. {"dims2", 224}, {"dims3", 3},
  249. };
  250. for (int i = 0; i < size_attr; i++) {
  251. std::string key(keys[i]);
  252. if (key == "names") {
  253. ASSERT_TRUE(
  254. std::string("input") ==
  255. std::string(static_cast<const char*>(values[i])));
  256. } else if (key == "scale") {
  257. float scale = *static_cast<float*>(values[i]);
  258. ASSERT_TRUE(std::fabs(scale - 0.007812) < 0.00001);
  259. } else if (key == "fl" || key == "pass_through") {
  260. uint8_t val = *static_cast<uint8_t*>(values[i]);
  261. if (key == "fl") {
  262. ASSERT_TRUE(val == 0);
  263. } else {
  264. ASSERT_TRUE(val == 1);
  265. }
  266. } else {
  267. uint32_t val = *static_cast<uint32_t*>(values[i]);
  268. ASSERT_TRUE(result_map[std::string(keys[i])] == val);
  269. }
  270. }
  271. }
  272. const char* keys[] = {"type", "fmt"};
  273. int info_size = SET_INFO_SIZE;
  274. int type = TENSOR_TYPE_UINT8;
  275. int fmt = TENSOR_FORMAT_NHWC;
  276. void* values[] = {static_cast<void*>(&type), static_cast<void*>(&fmt)};
  277. LITE_CAPI_CHECK(
  278. LITE_set_tensor_information(c_input_tensor, keys, values, info_size));
  279. ASSERT_TRUE(
  280. std::string(output_names[0]) ==
  281. std::string("MobilenetV1/Predictions/Reshape_1"));
  282. LITE_CAPI_CHECK(
  283. LITE_get_io_tensor(c_network, output_names[0], LITE_IO, &c_output_tensor));
  284. LITE_CAPI_CHECK(LITE_reset_tensor_memory(
  285. c_input_tensor, lite_tensor->get_memory_ptr(), data_length_in_byte));
  286. LITE_CAPI_CHECK(
  287. LITE_get_io_tensor(c_network, output_names[0], LITE_IO, &c_output_tensor));
  288. // LiteLayout tmp_output_layout;
  289. // LITE_get_tensor_layout(c_output_tensor, &tmp_output_layout);
  290. // tmp_output_layout.data_type = LiteDataType::LITE_FLOAT;
  291. // LITE_set_tensor_layout(c_output_tensor, tmp_output_layout);
  292. {
  293. const char* keys[] = {"want_float"};
  294. uint8_t want_float = 1;
  295. void* values[] = {static_cast<void*>(&want_float)};
  296. LITE_CAPI_CHECK(LITE_set_tensor_information(c_output_tensor, keys, values, 1));
  297. }
  298. LITE_CAPI_CHECK(LITE_forward(c_network));
  299. LITE_CAPI_CHECK(LITE_wait(c_network));
  300. ASSERT_TRUE(std::string(output_names[0]) == "MobilenetV1/Predictions/Reshape_1");
  301. ASSERT_EQ(output_names.size(), 1);
  302. {
  303. LiteLayout output_layout;
  304. LITE_get_tensor_layout(c_output_tensor, &output_layout);
  305. ASSERT_TRUE(output_layout.data_type == LITE_FLOAT);
  306. int size_attr = 0;
  307. LITE_CAPI_CHECK(LITE_get_tensor_attribute(
  308. c_output_tensor, nullptr, nullptr, &size_attr));
  309. ASSERT_TRUE(size_attr > 0);
  310. const char* keys[size_attr];
  311. void* values[size_attr];
  312. LITE_CAPI_CHECK(
  313. LITE_get_tensor_attribute(c_output_tensor, keys, values, &size_attr));
  314. ASSERT_TRUE(size_attr > 5);
  315. std::unordered_map<std::string, uint32_t> result_map = {
  316. {"zp", 0}, {"index", 0}, {"size_with_stride", 2002},
  317. {"stride", 0}, {"n_size", 2002}, {"n_elems", 1001},
  318. {"qnt_type", 2}, {"n_dims", 2}, {"type", 0},
  319. {"fmt", 2}, {"dims0", 1}, {"dims1", 1001},
  320. };
  321. for (int i = 0; i < size_attr; i++) {
  322. std::string key(keys[i]);
  323. if (key == "names") {
  324. ASSERT_TRUE(
  325. "MobilenetV1/Predictions/Reshape_1" ==
  326. std::string(static_cast<const char*>(values[i])));
  327. } else if (key == "scale") {
  328. float scale = *static_cast<float*>(values[i]);
  329. ASSERT_TRUE(std::fabs(scale - 1.0) < 0.00001);
  330. } else if (key == "fl" || key == "pass_through") {
  331. uint8_t val = *static_cast<uint8_t*>(values[i]);
  332. ASSERT_TRUE(val == 0);
  333. } else {
  334. uint32_t val = *static_cast<uint32_t*>(values[i]);
  335. ASSERT_TRUE(result_map[std::string(keys[i])] == val);
  336. }
  337. }
  338. }
  339. {
  340. uint32_t MaxClass[5];
  341. float fMaxProb[5];
  342. void* output_ptr;
  343. LITE_get_tensor_memory(c_output_tensor, &output_ptr);
  344. float* buffer = (float*)output_ptr;
  345. uint32_t sz = true_tensor->get_tensor_total_size_in_byte() / sizeof(float);
  346. GetTop(buffer, fMaxProb, MaxClass, sz, 5);
  347. std::vector<uint32_t> result_class = {
  348. 286, 464, 282, 357, 285,
  349. };
  350. std::vector<float> result_prob = {
  351. 0.407227, 0.365723, 0.090454, 0.018051, 0.013069,
  352. };
  353. for (int i = 0; i < 5; i++) {
  354. ASSERT_TRUE(result_class[i] == MaxClass[i]);
  355. ASSERT_TRUE(std::fabs(result_prob[i] - fMaxProb[i]) < 0.0001);
  356. }
  357. }
  358. {
  359. float* true_data = static_cast<float*>(true_tensor->get_memory_ptr());
  360. void* output_ptr;
  361. LITE_get_tensor_memory(c_output_tensor, &output_ptr);
  362. float* data1 = static_cast<float*>(output_ptr);
  363. size_t length = true_tensor->get_tensor_total_size_in_byte() / sizeof(float);
  364. for (size_t i = 0; i < length; i++) {
  365. ASSERT_LT(std::abs(data1[i] - true_data[i]), 1e-3);
  366. }
  367. }
  368. LITE_destroy_network(c_network);
  369. #undef SET_INFO_SIZE
  370. #undef TENSOR_FORMAT_NHWC
  371. #undef TENSOR_TYPE_UINT8
  372. }
  373. TEST(TestCapiNetWork, rknntest_set_info_two_input) {
  374. #define SET_INFO_SIZE 2
  375. #define TENSOR_TYPE_UINT8 3
  376. #define TENSOR_FORMAT_NHWC 1
  377. LiteConfig config;
  378. config.backend = LiteBackend::LITE_RK_NPU;
  379. config.device_type = LiteDeviceType::LITE_NPU;
  380. config.bare_model_cryption_name = nullptr;
  381. auto lite_tensor = lite::get_input_data("./model/cat_224x224.npy");
  382. auto lite_tensor_dog = lite::get_input_data("./model/dog_224x224.npy");
  383. auto true_tensor = lite::get_input_data("./output_data.npy");
  384. auto rknn_model = "./model/mobilenet_v1.rknn";
  385. LiteNetwork c_network;
  386. LITE_CAPI_CHECK(LITE_make_network_config(&c_network, config));
  387. LITE_CAPI_CHECK(LITE_load_model_from_path(c_network, rknn_model));
  388. size_t input_size, output_size;
  389. LITE_get_all_input_name(c_network, &input_size, nullptr);
  390. LITE_get_all_output_name(c_network, &output_size, nullptr);
  391. std::vector<const char*> input_names(input_size);
  392. std::vector<const char*> output_names(output_size);
  393. LiteTensor c_input_tensor, c_output_tensor;
  394. LITE_get_all_input_name(c_network, nullptr, input_names.data());
  395. LITE_get_all_output_name(c_network, nullptr, output_names.data());
  396. LITE_CAPI_CHECK(
  397. LITE_get_io_tensor(c_network, input_names[0], LITE_IO, &c_input_tensor));
  398. size_t input_length = 0;
  399. LITE_get_tensor_total_size_in_byte(c_input_tensor, &input_length);
  400. size_t data_length_in_byte = lite_tensor->get_tensor_total_size_in_byte();
  401. {
  402. LiteLayout input_layout;
  403. LITE_get_tensor_layout(c_input_tensor, &input_layout);
  404. ASSERT_TRUE(input_layout.data_type == LITE_INT8);
  405. std::vector<int> input_shape = {1, 224, 224, 3};
  406. for (size_t i = 0; i < input_layout.ndim; i++) {
  407. ASSERT_TRUE(input_layout.shapes[i] = input_shape[i]);
  408. }
  409. }
  410. const char* keys[] = {"type", "fmt"};
  411. int info_size = SET_INFO_SIZE;
  412. int type = TENSOR_TYPE_UINT8;
  413. int fmt = TENSOR_FORMAT_NHWC;
  414. void* values[] = {static_cast<void*>(&type), static_cast<void*>(&fmt)};
  415. LITE_CAPI_CHECK(
  416. LITE_set_tensor_information(c_input_tensor, keys, values, info_size));
  417. ASSERT_TRUE(
  418. std::string(output_names[0]) ==
  419. std::string("MobilenetV1/Predictions/Reshape_1"));
  420. LITE_CAPI_CHECK(
  421. LITE_get_io_tensor(c_network, output_names[0], LITE_IO, &c_output_tensor));
  422. LITE_CAPI_CHECK(LITE_reset_tensor_memory(
  423. c_input_tensor, lite_tensor->get_memory_ptr(), data_length_in_byte));
  424. LITE_CAPI_CHECK(
  425. LITE_get_io_tensor(c_network, output_names[0], LITE_IO, &c_output_tensor));
  426. {
  427. const char* keys[] = {"want_float"};
  428. uint8_t want_float = 1;
  429. void* values[] = {static_cast<void*>(&want_float)};
  430. LITE_CAPI_CHECK(LITE_set_tensor_information(c_output_tensor, keys, values, 1));
  431. }
  432. LITE_CAPI_CHECK(LITE_forward(c_network));
  433. LITE_CAPI_CHECK(LITE_wait(c_network));
  434. ASSERT_TRUE(std::string(output_names[0]) == "MobilenetV1/Predictions/Reshape_1");
  435. ASSERT_EQ(output_names.size(), 1);
  436. {
  437. uint32_t MaxClass[5];
  438. float fMaxProb[5];
  439. void* output_ptr;
  440. LITE_get_tensor_memory(c_output_tensor, &output_ptr);
  441. float* buffer = (float*)output_ptr;
  442. uint32_t sz = true_tensor->get_tensor_total_size_in_byte() / sizeof(float);
  443. GetTop(buffer, fMaxProb, MaxClass, sz, 5);
  444. std::vector<uint32_t> result_class = {
  445. 286, 464, 282, 357, 285,
  446. };
  447. std::vector<float> result_prob = {
  448. 0.407227, 0.365723, 0.090454, 0.018051, 0.013069,
  449. };
  450. for (int i = 0; i < 5; i++) {
  451. ASSERT_TRUE(result_class[i] == MaxClass[i]);
  452. ASSERT_TRUE(std::fabs(result_prob[i] - fMaxProb[i]) < 0.0001);
  453. }
  454. }
  455. {
  456. float* true_data = static_cast<float*>(true_tensor->get_memory_ptr());
  457. void* output_ptr;
  458. LITE_get_tensor_memory(c_output_tensor, &output_ptr);
  459. float* data1 = static_cast<float*>(output_ptr);
  460. size_t length = true_tensor->get_tensor_total_size_in_byte() / sizeof(float);
  461. for (size_t i = 0; i < length; i++) {
  462. ASSERT_LT(std::abs(data1[i] - true_data[i]), 1e-3);
  463. }
  464. }
  465. LITE_CAPI_CHECK(LITE_reset_tensor_memory(
  466. c_input_tensor, lite_tensor_dog->get_memory_ptr(), data_length_in_byte));
  467. LITE_CAPI_CHECK(LITE_forward(c_network));
  468. LITE_CAPI_CHECK(LITE_wait(c_network));
  469. ASSERT_TRUE(std::string(output_names[0]) == "MobilenetV1/Predictions/Reshape_1");
  470. ASSERT_EQ(output_names.size(), 1);
  471. {
  472. uint32_t MaxClass[5];
  473. float fMaxProb[5];
  474. void* output_ptr;
  475. LITE_get_tensor_memory(c_output_tensor, &output_ptr);
  476. float* buffer = (float*)output_ptr;
  477. uint32_t sz = true_tensor->get_tensor_total_size_in_byte() / sizeof(float);
  478. GetTop(buffer, fMaxProb, MaxClass, sz, 5);
  479. std::vector<float> result_prob = {
  480. 0.407227, 0.365723, 0.090454, 0.018051, 0.013069,
  481. };
  482. for (int i = 0; i < 5; i++) {
  483. ASSERT_FALSE(std::fabs(result_prob[i] - fMaxProb[i]) < 0.0001);
  484. }
  485. }
  486. LITE_destroy_network(c_network);
  487. #undef SET_INFO_SIZE
  488. #undef TENSOR_FORMAT_NHWC
  489. #undef TENSOR_TYPE_UINT8
  490. }
  491. #endif
  492. TEST(TestCapiNetWork, BasicResetOutput) {
  493. ForwardMgb;
  494. LiteNetwork c_network;
  495. LITE_CAPI_CHECK(LITE_make_default_network(&c_network));
  496. LoadNetwork;
  497. SetInput;
  498. LiteLayout output_layout{{1, 1000}, 2, LiteDataType::LITE_FLOAT};
  499. std::shared_ptr<float> ptr(new float[1000], [](float* ptr) { delete[] ptr; });
  500. const char* output_name;
  501. LITE_CAPI_CHECK(LITE_get_output_name(c_network, 0, &output_name));
  502. LITE_CAPI_CHECK(
  503. LITE_get_io_tensor(c_network, output_name, LITE_IO, &c_output_tensor));
  504. LITE_CAPI_CHECK(LITE_reset_tensor(c_output_tensor, output_layout, ptr.get()));
  505. ForwardNetwork;
  506. EXPECT_TRUE(lite::compare_memory<float>(
  507. ptr.get(), result_mgb->get_memory_ptr(),
  508. result_mgb->get_tensor_total_size_in_byte() / sizeof(float)));
  509. LITE_CAPI_CHECK(LITE_destroy_network(c_network));
  510. }
  511. TEST(TestCapiNetWork, BasicInplaceAndSingleThreadAffinity) {
  512. ForwardMgb;
  513. MakeNetwork;
  514. //! config the network with cpu inplace mode
  515. LITE_CAPI_CHECK(LITE_set_cpu_inplace_mode(c_network));
  516. LoadNetwork;
  517. //! set single thread affinith callback
  518. LITE_CAPI_CHECK(
  519. LITE_set_runtime_thread_affinity(c_network, single_thread_affinity));
  520. SetInput;
  521. ForwardNetwork;
  522. ASSERT_EQ(affinity_set, true);
  523. affinity_set = false;
  524. GetOutput;
  525. CompareResult;
  526. LITE_destroy_network(c_network);
  527. }
  528. TEST(TestCapiNetWork, UserAllocator) {
  529. ForwardMgb;
  530. MakeNetwork;
  531. LITE_CAPI_CHECK(LITE_set_memory_allocator(c_network, allocate, free));
  532. LoadNetwork;
  533. SetInput;
  534. ForwardNetwork;
  535. ASSERT_GE(m_nr_allocated, 1);
  536. GetOutput;
  537. CompareResult;
  538. LITE_CAPI_CHECK(LITE_destroy_network(c_network));
  539. ASSERT_EQ(m_nr_left, 0);
  540. }
  541. TEST(TestCapiNetWork, BasicMultiThread) {
  542. ForwardMgb;
  543. MakeNetwork;
  544. LITE_CAPI_CHECK(LITE_set_cpu_threads_number(c_network, NUMBER_THREDS));
  545. LoadNetwork;
  546. LITE_CAPI_CHECK(LITE_set_runtime_thread_affinity(c_network, multi_thread_affinity));
  547. SetInput;
  548. ForwardNetwork;
  549. for (size_t i = 0; i < NUMBER_THREDS; i++) {
  550. for (size_t j = i + 1; j < NUMBER_THREDS; j++) {
  551. ASSERT_NE(thread_ids[i], thread_ids[j]);
  552. }
  553. }
  554. for (size_t i = 0; i < NUMBER_THREDS; i++) {
  555. thread_ids[i] = std::thread::id();
  556. }
  557. GetOutput;
  558. CompareResult;
  559. LITE_CAPI_CHECK(LITE_destroy_network(c_network));
  560. }
  561. TEST(TestCapiNetWork, DeviceIO) {
  562. ForwardMgb;
  563. LiteNetwork c_network;
  564. LiteIO input_io = default_io;
  565. input_io.is_host = true;
  566. input_io.name = "data";
  567. LiteNetworkIO network_io = *default_network_io();
  568. network_io.inputs = &input_io;
  569. network_io.input_size = 1;
  570. LITE_CAPI_CHECK(LITE_make_network(&c_network, *default_config(), network_io));
  571. LoadNetwork;
  572. SetInput;
  573. ForwardNetwork;
  574. GetOutput;
  575. CompareResult;
  576. LITE_CAPI_CHECK(LITE_destroy_network(c_network));
  577. }
  578. TEST(TestCapiNetWork, StartCallBack) {
  579. ForwardMgb;
  580. MakeNetwork;
  581. LoadNetwork;
  582. LITE_CAPI_CHECK(LITE_set_start_callback(c_network, start_callback));
  583. SetInput;
  584. ForwardNetwork;
  585. GetOutput;
  586. CompareResult;
  587. ASSERT_TRUE(start_checked);
  588. LITE_CAPI_CHECK(LITE_destroy_network(c_network));
  589. }
  590. TEST(TestCapiNetWork, FinishCallBack) {
  591. ForwardMgb;
  592. MakeNetwork;
  593. LoadNetwork;
  594. LITE_CAPI_CHECK(LITE_set_finish_callback(c_network, finish_callback));
  595. SetInput;
  596. ForwardNetwork;
  597. GetOutput;
  598. CompareResult;
  599. ASSERT_TRUE(finish_checked);
  600. LITE_CAPI_CHECK(LITE_destroy_network(c_network));
  601. }
  602. TEST(TestCapiNetWork, BasicCryptAes) {
  603. ForwardMgb;
  604. LiteConfig c_config = *default_config();
  605. c_config.bare_model_cryption_name = "AES_default";
  606. LiteNetwork c_network;
  607. LITE_CAPI_CHECK(LITE_make_network(&c_network, c_config, *default_network_io()));
  608. std::string model_crypt_path = "./shufflenet_crypt_aes.mge";
  609. LITE_CAPI_CHECK(LITE_load_model_from_path(c_network, model_crypt_path.c_str()));
  610. SetInput;
  611. ForwardNetwork;
  612. GetOutput;
  613. CompareResult;
  614. LITE_CAPI_CHECK(LITE_destroy_network(c_network));
  615. }
  616. TEST(TestCapiNetWork, PackedCryptRc4) {
  617. ForwardMgb;
  618. MakeNetwork;
  619. std::string model_crypt_path = "./test_packed_model_rc4.lite";
  620. LITE_CAPI_CHECK(LITE_load_model_from_path(c_network, model_crypt_path.c_str()));
  621. SetInput;
  622. ForwardNetwork;
  623. GetOutput;
  624. CompareResult;
  625. LITE_CAPI_CHECK(LITE_destroy_network(c_network));
  626. }
  627. TEST(TestCapiNetWork, AsyncExec) {
  628. finished = false;
  629. ForwardMgb;
  630. LiteNetwork c_network;
  631. LiteConfig c_config = *default_config();
  632. c_config.options.var_sanity_check_first_run = false;
  633. LITE_CAPI_CHECK(LITE_make_network(&c_network, c_config, *default_network_io()));
  634. LITE_CAPI_CHECK(LITE_set_async_callback(c_network, finish_callback));
  635. LoadNetwork;
  636. SetInput;
  637. LITE_forward(c_network);
  638. size_t count = 0;
  639. while (finished == false) {
  640. count++;
  641. }
  642. ASSERT_GT(count, 0);
  643. finished = false;
  644. GetOutput;
  645. CompareResult;
  646. LITE_CAPI_CHECK(LITE_destroy_network(c_network));
  647. }
  648. TEST(TestCapiNetWork, OutputShapeOnly) {
  649. ForwardMgb;
  650. LiteNetwork c_network;
  651. LiteNetworkIO c_network_io = *default_network_io();
  652. LiteIO io_output = default_io;
  653. io_output.io_type = LiteIOType::LITE_IO_SHAPE;
  654. io_output.name = "TRUE_DIV(EXP[12065],reduce0[12067])[12077]";
  655. c_network_io.outputs = &io_output;
  656. c_network_io.output_size = 1;
  657. LITE_CAPI_CHECK(LITE_make_network(&c_network, *default_config(), c_network_io));
  658. LoadNetwork;
  659. SetInput;
  660. ForwardNetwork;
  661. GetOutput;
  662. size_t length = 0;
  663. LITE_CAPI_CHECK(LITE_get_tensor_total_size_in_byte(c_output_tensor, &length));
  664. ASSERT_EQ(length / sizeof(float), 1000);
  665. LITE_CAPI_CHECK(LITE_destroy_network(c_network));
  666. }
  667. TEST(TestCapiNetWork, ProfileIOdump) {
  668. ForwardMgb;
  669. MakeNetwork;
  670. LITE_CAPI_CHECK(LITE_enable_profile_performance(c_network, "./profile.json"));
  671. LoadNetwork;
  672. SetInput;
  673. ForwardNetwork;
  674. ASSERT_TRUE(fopen("./profile.json", "r"));
  675. LITE_CAPI_CHECK(LITE_enable_io_txt_dump(c_network, "./io_txt_dump.txt"));
  676. ForwardNetwork;
  677. ASSERT_TRUE(fopen("./io_txt_dump.txt", "r"));
  678. GetOutput;
  679. CompareResult;
  680. LITE_CAPI_CHECK(LITE_destroy_network(c_network));
  681. }
  682. TEST(TestCapiNetWork, GetDeviceType) {
  683. lite::Config config;
  684. auto lite_tensor = lite::get_input_data("./input_data.npy");
  685. std::string model_path = "./shufflenet.mge";
  686. MakeNetwork;
  687. LoadNetwork;
  688. LiteDeviceType devicetype;
  689. LITE_CAPI_CHECK(LITE_get_device_type(c_network, &devicetype));
  690. ASSERT_TRUE(devicetype == LiteDeviceType::LITE_CPU);
  691. LITE_CAPI_CHECK(LITE_destroy_network(c_network));
  692. }
  693. TEST(TestCapiNetWork, GetModelExtraInfo) {
  694. lite::Config config;
  695. std::string model_path = "./track_640_320_pack_model_rc4_with_info.lite";
  696. MakeNetwork;
  697. LITE_load_model_from_path(c_network, model_path.c_str());
  698. const char* info = nullptr;
  699. int info_size = 0;
  700. LITE_CAPI_CHECK(LITE_get_model_extra_info(c_network, &info, &info_size));
  701. ASSERT_TRUE(info_size > 0);
  702. printf("info %s \n", info);
  703. LITE_CAPI_CHECK(LITE_destroy_network(c_network));
  704. }
  705. TEST(TestCapiNetWork, TestWorkSpaceLimit) {
  706. lite::Config config;
  707. auto lite_tensor = lite::get_input_data("./input_data.npy");
  708. size_t data_length_in_byte = lite_tensor->get_tensor_total_size_in_byte();
  709. std::string model_path = "./shufflenet.mge";
  710. MakeNetwork;
  711. LoadNetwork;
  712. printf("go to config workspace limit\n");
  713. LITE_CAPI_CHECK(LITE_set_network_algo_workspace_limit(c_network, 1000));
  714. SetInput;
  715. ForwardNetwork;
  716. GetOutput;
  717. LITE_CAPI_CHECK(LITE_destroy_network(c_network));
  718. }
  719. TEST(TestCapiNetWork, TestShareWeights) {
  720. ForwardMgb;
  721. MakeNetwork;
  722. LoadNetwork;
  723. SetInput;
  724. ForwardNetwork;
  725. GetOutput;
  726. CompareResult;
  727. LiteNetwork c_network2;
  728. LITE_CAPI_CHECK(
  729. LITE_make_network(&c_network2, *default_config(), *default_network_io()));
  730. LITE_CAPI_CHECK(LITE_set_cpu_inplace_mode(c_network2));
  731. LITE_CAPI_CHECK(LITE_shared_weight_with_network(c_network2, c_network));
  732. int is_cpu_inplace_mode = false;
  733. LITE_CAPI_CHECK(LITE_is_cpu_inplace_mode(c_network2, &is_cpu_inplace_mode));
  734. ASSERT_EQ(is_cpu_inplace_mode, true);
  735. LiteTensor c_input_tensor2, c_output_tensor2;
  736. LITE_CAPI_CHECK(LITE_get_io_tensor(c_network2, "data", LITE_IO, &c_input_tensor2));
  737. LITE_CAPI_CHECK(LITE_reset_tensor_memory(
  738. c_input_tensor2, lite_tensor->get_memory_ptr(),
  739. lite_tensor->get_tensor_total_size_in_byte()));
  740. LITE_CAPI_CHECK(LITE_forward(c_network2));
  741. LITE_CAPI_CHECK(LITE_wait(c_network2));
  742. LITE_CAPI_CHECK(
  743. LITE_get_io_tensor(c_network2, output_name, LITE_IO, &c_output_tensor2));
  744. void* output_ptr2;
  745. LITE_CAPI_CHECK(LITE_get_tensor_memory(c_output_tensor2, &output_ptr2));
  746. EXPECT_TRUE(lite::compare_memory<float>(
  747. output_ptr2, result_mgb->get_memory_ptr(),
  748. result_mgb->get_tensor_total_size_in_byte() / sizeof(float)));
  749. LITE_CAPI_CHECK(LITE_destroy_network(c_network));
  750. LITE_CAPI_CHECK(LITE_destroy_network(c_network2));
  751. }
  752. #endif
  753. // vim: syntax=cpp.doxygen foldmethod=marker foldmarker=f{{{,f}}}

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