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

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