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 31 kB

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

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