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.

net.cpp 22 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886
  1. // Tencent is pleased to support the open source community by making ncnn available.
  2. //
  3. // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved.
  4. //
  5. // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
  6. // in compliance with the License. You may obtain a copy of the License at
  7. //
  8. // https://opensource.org/licenses/BSD-3-Clause
  9. //
  10. // Unless required by applicable law or agreed to in writing, software distributed
  11. // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  12. // CONDITIONS OF ANY KIND, either express or implied. See the License for the
  13. // specific language governing permissions and limitations under the License.
  14. #include "net.h"
  15. #include "layer_type.h"
  16. #include "modelbin.h"
  17. #include "paramdict.h"
  18. #include <stdio.h>
  19. #include <string.h>
  20. #ifdef _OPENMP
  21. #include <omp.h>
  22. #endif // _OPENMP
  23. #if NCNN_BENCHMARK
  24. #include "benchmark.h"
  25. #endif // NCNN_BENCHMARK
  26. namespace ncnn {
  27. Net::Net()
  28. {
  29. }
  30. Net::~Net()
  31. {
  32. clear();
  33. }
  34. #if NCNN_STRING
  35. int Net::register_custom_layer(const char* type, layer_creator_func creator)
  36. {
  37. int typeindex = layer_to_index(type);
  38. if (typeindex != -1)
  39. {
  40. fprintf(stderr, "can not register build-in layer type %s\n", type);
  41. return -1;
  42. }
  43. int custom_index = custom_layer_to_index(type);
  44. if (custom_index == -1)
  45. {
  46. struct layer_registry_entry entry = { type, creator };
  47. custom_layer_registry.push_back(entry);
  48. }
  49. else
  50. {
  51. fprintf(stderr, "overwrite existing custom layer type %s\n", type);
  52. custom_layer_registry[custom_index].name = type;
  53. custom_layer_registry[custom_index].creator = creator;
  54. }
  55. return 0;
  56. }
  57. #endif // NCNN_STRING
  58. int Net::register_custom_layer(int index, layer_creator_func creator)
  59. {
  60. int custom_index = index & ~LayerType::CustomBit;
  61. if (index == custom_index)
  62. {
  63. fprintf(stderr, "can not register build-in layer index %d\n", custom_index);
  64. return -1;
  65. }
  66. if ((int)custom_layer_registry.size() <= custom_index)
  67. {
  68. #if NCNN_STRING
  69. struct layer_registry_entry dummy = { "", 0 };
  70. #else
  71. struct layer_registry_entry dummy = { 0 };
  72. #endif // NCNN_STRING
  73. custom_layer_registry.resize(custom_index + 1, dummy);
  74. }
  75. if (custom_layer_registry[custom_index].creator)
  76. {
  77. fprintf(stderr, "overwrite existing custom layer index %d\n", custom_index);
  78. }
  79. custom_layer_registry[custom_index].creator = creator;
  80. return 0;
  81. }
  82. #if NCNN_STDIO
  83. #if NCNN_STRING
  84. int Net::load_param(FILE* fp)
  85. {
  86. int magic = 0;
  87. fscanf(fp, "%d", &magic);
  88. if (magic != 7767517)
  89. {
  90. fprintf(stderr, "param is too old, please regenerate\n");
  91. return -1;
  92. }
  93. // parse
  94. int layer_count = 0;
  95. int blob_count = 0;
  96. fscanf(fp, "%d %d", &layer_count, &blob_count);
  97. layers.resize(layer_count);
  98. blobs.resize(blob_count);
  99. ParamDict pd;
  100. int layer_index = 0;
  101. int blob_index = 0;
  102. while (!feof(fp))
  103. {
  104. int nscan = 0;
  105. char layer_type[256];
  106. char layer_name[256];
  107. int bottom_count = 0;
  108. int top_count = 0;
  109. nscan = fscanf(fp, "%256s %256s %d %d", layer_type, layer_name, &bottom_count, &top_count);
  110. if (nscan != 4)
  111. {
  112. continue;
  113. }
  114. Layer* layer = create_layer(layer_type);
  115. if (!layer)
  116. {
  117. layer = create_custom_layer(layer_type);
  118. }
  119. if (!layer)
  120. {
  121. fprintf(stderr, "layer %s not exists or registered\n", layer_type);
  122. clear();
  123. return -1;
  124. }
  125. layer->type = std::string(layer_type);
  126. layer->name = std::string(layer_name);
  127. // fprintf(stderr, "new layer %d %s\n", layer_index, layer_name);
  128. layer->bottoms.resize(bottom_count);
  129. for (int i=0; i<bottom_count; i++)
  130. {
  131. char bottom_name[256];
  132. nscan = fscanf(fp, "%256s", bottom_name);
  133. if (nscan != 1)
  134. {
  135. continue;
  136. }
  137. int bottom_blob_index = find_blob_index_by_name(bottom_name);
  138. if (bottom_blob_index == -1)
  139. {
  140. Blob& blob = blobs[blob_index];
  141. bottom_blob_index = blob_index;
  142. blob.name = std::string(bottom_name);
  143. // fprintf(stderr, "new blob %s\n", bottom_name);
  144. blob_index++;
  145. }
  146. Blob& blob = blobs[bottom_blob_index];
  147. blob.consumers.push_back(layer_index);
  148. layer->bottoms[i] = bottom_blob_index;
  149. }
  150. layer->tops.resize(top_count);
  151. for (int i=0; i<top_count; i++)
  152. {
  153. Blob& blob = blobs[blob_index];
  154. char blob_name[256];
  155. nscan = fscanf(fp, "%256s", blob_name);
  156. if (nscan != 1)
  157. {
  158. continue;
  159. }
  160. blob.name = std::string(blob_name);
  161. // fprintf(stderr, "new blob %s\n", blob_name);
  162. blob.producer = layer_index;
  163. layer->tops[i] = blob_index;
  164. blob_index++;
  165. }
  166. // layer specific params
  167. int pdlr = pd.load_param(fp);
  168. if (pdlr != 0)
  169. {
  170. fprintf(stderr, "ParamDict load_param failed\n");
  171. continue;
  172. }
  173. int lr = layer->load_param(pd);
  174. if (lr != 0)
  175. {
  176. fprintf(stderr, "layer load_param failed\n");
  177. continue;
  178. }
  179. layers[layer_index] = layer;
  180. layer_index++;
  181. }
  182. return 0;
  183. }
  184. int Net::load_param(const char* protopath)
  185. {
  186. FILE* fp = fopen(protopath, "rb");
  187. if (!fp)
  188. {
  189. fprintf(stderr, "fopen %s failed\n", protopath);
  190. return -1;
  191. }
  192. int ret = load_param(fp);
  193. fclose(fp);
  194. return ret;
  195. }
  196. #endif // NCNN_STRING
  197. int Net::load_param_bin(FILE* fp)
  198. {
  199. int magic = 0;
  200. fread(&magic, sizeof(int), 1, fp);
  201. if (magic != 7767517)
  202. {
  203. fprintf(stderr, "param is too old, please regenerate\n");
  204. return -1;
  205. }
  206. int layer_count = 0;
  207. fread(&layer_count, sizeof(int), 1, fp);
  208. int blob_count = 0;
  209. fread(&blob_count, sizeof(int), 1, fp);
  210. layers.resize(layer_count);
  211. blobs.resize(blob_count);
  212. ParamDict pd;
  213. for (int i=0; i<layer_count; i++)
  214. {
  215. int typeindex;
  216. fread(&typeindex, sizeof(int), 1, fp);
  217. int bottom_count;
  218. fread(&bottom_count, sizeof(int), 1, fp);
  219. int top_count;
  220. fread(&top_count, sizeof(int), 1, fp);
  221. Layer* layer = create_layer(typeindex);
  222. if (!layer)
  223. {
  224. int custom_index = typeindex & ~LayerType::CustomBit;
  225. layer = create_custom_layer(custom_index);
  226. }
  227. if (!layer)
  228. {
  229. fprintf(stderr, "layer %d not exists or registered\n", typeindex);
  230. clear();
  231. return -1;
  232. }
  233. // layer->type = std::string(layer_type);
  234. // layer->name = std::string(layer_name);
  235. // fprintf(stderr, "new layer %d\n", typeindex);
  236. layer->bottoms.resize(bottom_count);
  237. for (int j=0; j<bottom_count; j++)
  238. {
  239. int bottom_blob_index;
  240. fread(&bottom_blob_index, sizeof(int), 1, fp);
  241. Blob& blob = blobs[bottom_blob_index];
  242. blob.consumers.push_back(i);
  243. layer->bottoms[j] = bottom_blob_index;
  244. }
  245. layer->tops.resize(top_count);
  246. for (int j=0; j<top_count; j++)
  247. {
  248. int top_blob_index;
  249. fread(&top_blob_index, sizeof(int), 1, fp);
  250. Blob& blob = blobs[top_blob_index];
  251. // blob.name = std::string(blob_name);
  252. // fprintf(stderr, "new blob %s\n", blob_name);
  253. blob.producer = i;
  254. layer->tops[j] = top_blob_index;
  255. }
  256. // layer specific params
  257. int pdlr = pd.load_param_bin(fp);
  258. if (pdlr != 0)
  259. {
  260. fprintf(stderr, "ParamDict load_param failed\n");
  261. continue;
  262. }
  263. int lr = layer->load_param(pd);
  264. if (lr != 0)
  265. {
  266. fprintf(stderr, "layer load_param failed\n");
  267. continue;
  268. }
  269. layers[i] = layer;
  270. }
  271. return 0;
  272. }
  273. int Net::load_param_bin(const char* protopath)
  274. {
  275. FILE* fp = fopen(protopath, "rb");
  276. if (!fp)
  277. {
  278. fprintf(stderr, "fopen %s failed\n", protopath);
  279. return -1;
  280. }
  281. int ret = load_param_bin(fp);
  282. fclose(fp);
  283. return ret;
  284. }
  285. int Net::load_model(FILE* fp)
  286. {
  287. // load file
  288. int ret = 0;
  289. ModelBinFromStdio mb(fp);
  290. for (size_t i=0; i<layers.size(); i++)
  291. {
  292. Layer* layer = layers[i];
  293. int lret = layer->load_model(mb);
  294. if (lret != 0)
  295. {
  296. fprintf(stderr, "layer load_model %d failed\n", (int)i);
  297. ret = -1;
  298. break;
  299. }
  300. }
  301. return ret;
  302. }
  303. int Net::load_model(const char* modelpath)
  304. {
  305. FILE* fp = fopen(modelpath, "rb");
  306. if (!fp)
  307. {
  308. fprintf(stderr, "fopen %s failed\n", modelpath);
  309. return -1;
  310. }
  311. int ret = load_model(fp);
  312. fclose(fp);
  313. return ret;
  314. }
  315. #endif // NCNN_STDIO
  316. int Net::load_param(const unsigned char* _mem)
  317. {
  318. if ((unsigned long)_mem & 0x3)
  319. {
  320. // reject unaligned memory
  321. fprintf(stderr, "memory not 32-bit aligned at %p\n", _mem);
  322. return 0;
  323. }
  324. const unsigned char* mem = _mem;
  325. int magic = *(int*)(mem);
  326. mem += 4;
  327. if (magic != 7767517)
  328. {
  329. fprintf(stderr, "param is too old, please regenerate\n");
  330. return 0;
  331. }
  332. int layer_count = *(int*)(mem);
  333. mem += 4;
  334. int blob_count = *(int*)(mem);
  335. mem += 4;
  336. layers.resize(layer_count);
  337. blobs.resize(blob_count);
  338. ParamDict pd;
  339. for (int i=0; i<layer_count; i++)
  340. {
  341. int typeindex = *(int*)mem;
  342. mem += 4;
  343. int bottom_count = *(int*)mem;
  344. mem += 4;
  345. int top_count = *(int*)mem;
  346. mem += 4;
  347. Layer* layer = create_layer(typeindex);
  348. if (!layer)
  349. {
  350. int custom_index = typeindex & ~LayerType::CustomBit;
  351. layer = create_custom_layer(custom_index);
  352. }
  353. if (!layer)
  354. {
  355. fprintf(stderr, "layer %d not exists or registered\n", typeindex);
  356. clear();
  357. return 0;
  358. }
  359. // layer->type = std::string(layer_type);
  360. // layer->name = std::string(layer_name);
  361. // fprintf(stderr, "new layer %d\n", typeindex);
  362. layer->bottoms.resize(bottom_count);
  363. for (int j=0; j<bottom_count; j++)
  364. {
  365. int bottom_blob_index = *(int*)mem;
  366. mem += 4;
  367. Blob& blob = blobs[bottom_blob_index];
  368. blob.consumers.push_back(i);
  369. layer->bottoms[j] = bottom_blob_index;
  370. }
  371. layer->tops.resize(top_count);
  372. for (int j=0; j<top_count; j++)
  373. {
  374. int top_blob_index = *(int*)mem;
  375. mem += 4;
  376. Blob& blob = blobs[top_blob_index];
  377. // blob.name = std::string(blob_name);
  378. // fprintf(stderr, "new blob %s\n", blob_name);
  379. blob.producer = i;
  380. layer->tops[j] = top_blob_index;
  381. }
  382. // layer specific params
  383. int pdlr = pd.load_param(mem);
  384. if (pdlr != 0)
  385. {
  386. fprintf(stderr, "ParamDict load_param failed\n");
  387. continue;
  388. }
  389. int lr = layer->load_param(pd);
  390. if (lr != 0)
  391. {
  392. fprintf(stderr, "layer load_param failed\n");
  393. continue;
  394. }
  395. layers[i] = layer;
  396. }
  397. return mem - _mem;
  398. }
  399. int Net::load_model(const unsigned char* _mem)
  400. {
  401. if ((unsigned long)_mem & 0x3)
  402. {
  403. // reject unaligned memory
  404. fprintf(stderr, "memory not 32-bit aligned at %p\n", _mem);
  405. return 0;
  406. }
  407. const unsigned char* mem = _mem;
  408. ModelBinFromMemory mb(mem);
  409. for (size_t i=0; i<layers.size(); i++)
  410. {
  411. Layer* layer = layers[i];
  412. int lret = layer->load_model(mb);
  413. if (lret != 0)
  414. {
  415. fprintf(stderr, "layer load_model failed\n");
  416. return -1;
  417. }
  418. }
  419. return mem - _mem;
  420. }
  421. void Net::clear()
  422. {
  423. blobs.clear();
  424. for (size_t i=0; i<layers.size(); i++)
  425. {
  426. delete layers[i];
  427. }
  428. layers.clear();
  429. }
  430. Extractor Net::create_extractor() const
  431. {
  432. return Extractor(this, blobs.size());
  433. }
  434. #if NCNN_STRING
  435. int Net::find_blob_index_by_name(const char* name) const
  436. {
  437. for (size_t i=0; i<blobs.size(); i++)
  438. {
  439. const Blob& blob = blobs[i];
  440. if (blob.name == name)
  441. {
  442. return i;
  443. }
  444. }
  445. fprintf(stderr, "find_blob_index_by_name %s failed\n", name);
  446. return -1;
  447. }
  448. int Net::find_layer_index_by_name(const char* name) const
  449. {
  450. for (size_t i=0; i<layers.size(); i++)
  451. {
  452. const Layer* layer = layers[i];
  453. if (layer->name == name)
  454. {
  455. return i;
  456. }
  457. }
  458. fprintf(stderr, "find_layer_index_by_name %s failed\n", name);
  459. return -1;
  460. }
  461. int Net::custom_layer_to_index(const char* type)
  462. {
  463. const int custom_layer_registry_entry_count = custom_layer_registry.size();
  464. for (int i=0; i<custom_layer_registry_entry_count; i++)
  465. {
  466. if (strcmp(type, custom_layer_registry[i].name) == 0)
  467. return i;
  468. }
  469. return -1;
  470. }
  471. Layer* Net::create_custom_layer(const char* type)
  472. {
  473. int index = custom_layer_to_index(type);
  474. if (index == -1)
  475. return 0;
  476. return create_custom_layer(index);
  477. }
  478. #endif // NCNN_STRING
  479. Layer* Net::create_custom_layer(int index)
  480. {
  481. const int custom_layer_registry_entry_count = custom_layer_registry.size();
  482. if (index < 0 || index >= custom_layer_registry_entry_count)
  483. return 0;
  484. layer_creator_func layer_creator = custom_layer_registry[index].creator;
  485. if (!layer_creator)
  486. return 0;
  487. return layer_creator();
  488. }
  489. int Net::forward_layer(int layer_index, std::vector<Mat>& blob_mats, bool lightmode) const
  490. {
  491. const Layer* layer = layers[layer_index];
  492. // fprintf(stderr, "forward_layer %d %s\n", layer_index, layer->name.c_str());
  493. if (layer->one_blob_only)
  494. {
  495. // load bottom blob
  496. int bottom_blob_index = layer->bottoms[0];
  497. int top_blob_index = layer->tops[0];
  498. if (blob_mats[bottom_blob_index].dims == 0)
  499. {
  500. int ret = forward_layer(blobs[bottom_blob_index].producer, blob_mats, lightmode);
  501. if (ret != 0)
  502. return ret;
  503. }
  504. Mat bottom_blob = blob_mats[bottom_blob_index];
  505. if (lightmode)
  506. {
  507. // delete after taken in light mode
  508. blob_mats[bottom_blob_index].release();
  509. // deep copy for inplace forward if data is shared
  510. if (layer->support_inplace && *bottom_blob.refcount != 1)
  511. {
  512. bottom_blob = bottom_blob.clone();
  513. }
  514. }
  515. // forward
  516. if (lightmode && layer->support_inplace)
  517. {
  518. Mat& bottom_top_blob = bottom_blob;
  519. #if NCNN_BENCHMARK
  520. double start = get_current_time();
  521. int ret = layer->forward_inplace(bottom_top_blob);
  522. double end = get_current_time();
  523. benchmark(layer, bottom_top_blob, bottom_top_blob, start, end);
  524. #else
  525. int ret = layer->forward_inplace(bottom_top_blob);
  526. #endif // NCNN_BENCHMARK
  527. if (ret != 0)
  528. return ret;
  529. // store top blob
  530. blob_mats[top_blob_index] = bottom_top_blob;
  531. }
  532. else
  533. {
  534. Mat top_blob;
  535. #if NCNN_BENCHMARK
  536. double start = get_current_time();
  537. int ret = layer->forward(bottom_blob, top_blob);
  538. double end = get_current_time();
  539. benchmark(layer, bottom_blob, top_blob, start, end);
  540. #else
  541. int ret = layer->forward(bottom_blob, top_blob);
  542. #endif // NCNN_BENCHMARK
  543. if (ret != 0)
  544. return ret;
  545. // store top blob
  546. blob_mats[top_blob_index] = top_blob;
  547. }
  548. }
  549. else
  550. {
  551. // load bottom blobs
  552. std::vector<Mat> bottom_blobs;
  553. bottom_blobs.resize(layer->bottoms.size());
  554. for (size_t i=0; i<layer->bottoms.size(); i++)
  555. {
  556. int bottom_blob_index = layer->bottoms[i];
  557. if (blob_mats[bottom_blob_index].dims == 0)
  558. {
  559. int ret = forward_layer(blobs[bottom_blob_index].producer, blob_mats, lightmode);
  560. if (ret != 0)
  561. return ret;
  562. }
  563. bottom_blobs[i] = blob_mats[bottom_blob_index];
  564. if (lightmode)
  565. {
  566. // delete after taken in light mode
  567. blob_mats[bottom_blob_index].release();
  568. // deep copy for inplace forward if data is shared
  569. if (layer->support_inplace && *bottom_blobs[i].refcount != 1)
  570. {
  571. bottom_blobs[i] = bottom_blobs[i].clone();
  572. }
  573. }
  574. }
  575. // forward
  576. if (lightmode && layer->support_inplace)
  577. {
  578. std::vector<Mat>& bottom_top_blobs = bottom_blobs;
  579. #if NCNN_BENCHMARK
  580. double start = get_current_time();
  581. int ret = layer->forward_inplace(bottom_top_blobs);
  582. double end = get_current_time();
  583. benchmark(layer, start, end);
  584. #else
  585. int ret = layer->forward_inplace(bottom_top_blobs);
  586. #endif // NCNN_BENCHMARK
  587. if (ret != 0)
  588. return ret;
  589. // store top blobs
  590. for (size_t i=0; i<layer->tops.size(); i++)
  591. {
  592. int top_blob_index = layer->tops[i];
  593. blob_mats[top_blob_index] = bottom_top_blobs[i];
  594. }
  595. }
  596. else
  597. {
  598. std::vector<Mat> top_blobs;
  599. top_blobs.resize(layer->tops.size());
  600. #if NCNN_BENCHMARK
  601. double start = get_current_time();
  602. int ret = layer->forward(bottom_blobs, top_blobs);
  603. double end = get_current_time();
  604. benchmark(layer, start, end);
  605. #else
  606. int ret = layer->forward(bottom_blobs, top_blobs);
  607. #endif // NCNN_BENCHMARK
  608. if (ret != 0)
  609. return ret;
  610. // store top blobs
  611. for (size_t i=0; i<layer->tops.size(); i++)
  612. {
  613. int top_blob_index = layer->tops[i];
  614. blob_mats[top_blob_index] = top_blobs[i];
  615. }
  616. }
  617. }
  618. // fprintf(stderr, "forward_layer %d %s done\n", layer_index, layer->name.c_str());
  619. // const Mat& blob = blob_mats[layer->tops[0]];
  620. // fprintf(stderr, "[%-2d %-16s %-16s] %d blobs count = %-3d size = %-3d x %-3d\n", layer_index, layer->type.c_str(), layer->name.c_str(), layer->tops[0], blob.c, blob.h, blob.w);
  621. return 0;
  622. }
  623. Extractor::Extractor(const Net* _net, int blob_count) : net(_net)
  624. {
  625. blob_mats.resize(blob_count);
  626. lightmode = true;
  627. num_threads = 0;
  628. }
  629. void Extractor::set_light_mode(bool enable)
  630. {
  631. lightmode = enable;
  632. }
  633. void Extractor::set_num_threads(int _num_threads)
  634. {
  635. num_threads = _num_threads;
  636. }
  637. int Extractor::input(int blob_index, const Mat& in)
  638. {
  639. if (blob_index < 0 || blob_index >= (int)blob_mats.size())
  640. return -1;
  641. blob_mats[blob_index] = in;
  642. return 0;
  643. }
  644. int Extractor::extract(int blob_index, Mat& feat)
  645. {
  646. if (blob_index < 0 || blob_index >= (int)blob_mats.size())
  647. return -1;
  648. int ret = 0;
  649. if (blob_mats[blob_index].dims == 0)
  650. {
  651. int layer_index = net->blobs[blob_index].producer;
  652. #ifdef _OPENMP
  653. int dynamic_current = 0;
  654. int num_threads_current = 1;
  655. if (num_threads)
  656. {
  657. dynamic_current = omp_get_dynamic();
  658. num_threads_current = omp_get_num_threads();
  659. omp_set_dynamic(0);
  660. omp_set_num_threads(num_threads);
  661. }
  662. #endif
  663. ret = net->forward_layer(layer_index, blob_mats, lightmode);
  664. #ifdef _OPENMP
  665. if (num_threads)
  666. {
  667. omp_set_dynamic(dynamic_current);
  668. omp_set_num_threads(num_threads_current);
  669. }
  670. #endif
  671. }
  672. feat = blob_mats[blob_index];
  673. return ret;
  674. }
  675. #if NCNN_STRING
  676. int Extractor::input(const char* blob_name, const Mat& in)
  677. {
  678. int blob_index = net->find_blob_index_by_name(blob_name);
  679. if (blob_index == -1)
  680. return -1;
  681. blob_mats[blob_index] = in;
  682. return 0;
  683. }
  684. int Extractor::extract(const char* blob_name, Mat& feat)
  685. {
  686. int blob_index = net->find_blob_index_by_name(blob_name);
  687. if (blob_index == -1)
  688. return -1;
  689. int ret = 0;
  690. if (blob_mats[blob_index].dims == 0)
  691. {
  692. int layer_index = net->blobs[blob_index].producer;
  693. #ifdef _OPENMP
  694. int dynamic_current = 0;
  695. int num_threads_current = 1;
  696. if (num_threads)
  697. {
  698. dynamic_current = omp_get_dynamic();
  699. num_threads_current = omp_get_num_threads();
  700. omp_set_dynamic(0);
  701. omp_set_num_threads(num_threads);
  702. }
  703. #endif
  704. ret = net->forward_layer(layer_index, blob_mats, lightmode);
  705. #ifdef _OPENMP
  706. if (num_threads)
  707. {
  708. omp_set_dynamic(dynamic_current);
  709. omp_set_num_threads(num_threads_current);
  710. }
  711. #endif
  712. }
  713. feat = blob_mats[blob_index];
  714. return ret;
  715. }
  716. #endif // NCNN_STRING
  717. } // namespace ncnn