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

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