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.

slice_arm.cpp 28 kB

6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
5 years ago
5 years ago
5 years ago
5 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887
  1. // Tencent is pleased to support the open source community by making ncnn available.
  2. //
  3. // Copyright (C) 2019 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 "slice_arm.h"
  15. namespace ncnn {
  16. Slice_arm::Slice_arm()
  17. {
  18. #if __ARM_NEON
  19. support_packing = true;
  20. #if __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
  21. support_fp16_storage = true;
  22. #endif
  23. #endif // __ARM_NEON
  24. #if NCNN_BF16
  25. support_bf16_storage = true;
  26. #endif
  27. }
  28. int Slice_arm::forward(const std::vector<Mat>& bottom_blobs, std::vector<Mat>& top_blobs, const Option& opt) const
  29. {
  30. int elembits = bottom_blobs[0].elembits();
  31. #if __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
  32. if (opt.use_fp16_storage && elembits == 16)
  33. return forward_bf16s_fp16s(bottom_blobs, top_blobs, opt);
  34. #endif
  35. #if NCNN_BF16
  36. if (opt.use_bf16_storage && elembits == 16)
  37. return forward_bf16s_fp16s(bottom_blobs, top_blobs, opt);
  38. #endif
  39. const Mat& bottom_blob = bottom_blobs[0];
  40. int dims = bottom_blob.dims;
  41. size_t elemsize = bottom_blob.elemsize;
  42. int elempack = bottom_blob.elempack;
  43. const int* slices_ptr = slices;
  44. int positive_axis = axis < 0 ? dims + axis : axis;
  45. if (dims == 1) // positive_axis == 0
  46. {
  47. // slice vector
  48. int w = bottom_blob.w * elempack;
  49. int q = 0;
  50. for (size_t i = 0; i < top_blobs.size(); i++)
  51. {
  52. int slice = slices_ptr[i];
  53. if (slice == -233)
  54. {
  55. slice = (w - q) / (top_blobs.size() - i);
  56. }
  57. int out_elempack = 1;
  58. #if __ARM_NEON
  59. if (opt.use_packing_layout)
  60. {
  61. out_elempack = slice % 4 == 0 ? 4 : 1;
  62. }
  63. #endif
  64. size_t out_elemsize = elemsize / elempack * out_elempack;
  65. Mat& top_blob = top_blobs[i];
  66. top_blob.create(slice / out_elempack, out_elemsize, out_elempack, opt.blob_allocator);
  67. if (top_blob.empty())
  68. return -100;
  69. const float* ptr = (const float*)bottom_blob + q;
  70. float* outptr = top_blob;
  71. memcpy(outptr, ptr, top_blob.w * top_blob.elemsize);
  72. q += slice;
  73. }
  74. }
  75. if (dims == 2 && positive_axis == 0)
  76. {
  77. // slice image height
  78. int w = bottom_blob.w;
  79. int h = bottom_blob.h * elempack;
  80. int q = 0;
  81. for (size_t i = 0; i < top_blobs.size(); i++)
  82. {
  83. int slice = slices_ptr[i];
  84. if (slice == -233)
  85. {
  86. slice = (h - q) / (top_blobs.size() - i);
  87. }
  88. int out_elempack = 1;
  89. #if __ARM_NEON
  90. if (opt.use_packing_layout)
  91. {
  92. out_elempack = slice % 4 == 0 ? 4 : 1;
  93. }
  94. #endif
  95. size_t out_elemsize = elemsize / elempack * out_elempack;
  96. Mat& top_blob = top_blobs[i];
  97. top_blob.create(w, slice / out_elempack, out_elemsize, out_elempack, opt.blob_allocator);
  98. if (top_blob.empty())
  99. return -100;
  100. q += slice;
  101. }
  102. size_t out_elemsize = top_blobs[0].elemsize;
  103. int out_elempack = top_blobs[0].elempack;
  104. for (size_t i = 0; i < top_blobs.size(); i++)
  105. {
  106. out_elemsize = std::min(out_elemsize, top_blobs[i].elemsize);
  107. out_elempack = std::min(out_elempack, top_blobs[i].elempack);
  108. }
  109. Mat bottom_blob_unpacked = bottom_blob;
  110. if (elempack > out_elempack)
  111. {
  112. convert_packing(bottom_blob, bottom_blob_unpacked, out_elempack, opt);
  113. }
  114. const float* ptr = bottom_blob_unpacked;
  115. for (size_t i = 0; i < top_blobs.size(); i++)
  116. {
  117. Mat& top_blob = top_blobs[i];
  118. if (out_elempack == 1 && top_blob.elempack == 4)
  119. {
  120. for (int j = 0; j < top_blob.h; j++)
  121. {
  122. const float* r0 = ptr;
  123. const float* r1 = ptr + w;
  124. const float* r2 = ptr + w * 2;
  125. const float* r3 = ptr + w * 3;
  126. float* outptr0 = top_blob.row(j);
  127. for (int j = 0; j < w; j++)
  128. {
  129. outptr0[0] = *r0++;
  130. outptr0[1] = *r1++;
  131. outptr0[2] = *r2++;
  132. outptr0[3] = *r3++;
  133. outptr0 += 4;
  134. }
  135. ptr += w * 4;
  136. }
  137. }
  138. else // if (out_elempack == 1 && top_blob.elempack == 1) if (out_elempack == 4 && top_blob.elempack == 4)
  139. {
  140. int size = w * top_blob.h;
  141. float* outptr = top_blob;
  142. memcpy(outptr, ptr, size * top_blob.elemsize);
  143. ptr += size * top_blob.elempack;
  144. }
  145. }
  146. }
  147. if (dims == 2 && positive_axis == 1)
  148. {
  149. // slice image width
  150. int w = bottom_blob.w;
  151. int h = bottom_blob.h;
  152. int q = 0;
  153. for (size_t i = 0; i < top_blobs.size(); i++)
  154. {
  155. int slice = slices_ptr[i];
  156. if (slice == -233)
  157. {
  158. slice = (w - q) / (top_blobs.size() - i);
  159. }
  160. Mat& top_blob = top_blobs[i];
  161. top_blob.create(slice, h, elemsize, elempack, opt.blob_allocator);
  162. if (top_blob.empty())
  163. return -100;
  164. q += slice;
  165. }
  166. #pragma omp parallel for num_threads(opt.num_threads)
  167. for (int j = 0; j < h; j++)
  168. {
  169. const float* ptr = bottom_blob.row(j);
  170. for (size_t i = 0; i < top_blobs.size(); i++)
  171. {
  172. Mat& top_blob = top_blobs[i];
  173. float* outptr = top_blob.row(j);
  174. memcpy(outptr, ptr, top_blob.w * elemsize);
  175. ptr += top_blob.w * elempack;
  176. }
  177. }
  178. }
  179. if (dims == 3 && positive_axis == 0)
  180. {
  181. // slice dim channel
  182. int w = bottom_blob.w;
  183. int h = bottom_blob.h;
  184. int channels = bottom_blob.c * elempack;
  185. int q = 0;
  186. for (size_t i = 0; i < top_blobs.size(); i++)
  187. {
  188. int slice = slices_ptr[i];
  189. if (slice == -233)
  190. {
  191. slice = (channels - q) / (top_blobs.size() - i);
  192. }
  193. int out_elempack = 1;
  194. #if __ARM_NEON
  195. if (opt.use_packing_layout)
  196. {
  197. out_elempack = slice % 4 == 0 ? 4 : 1;
  198. }
  199. #endif
  200. size_t out_elemsize = elemsize / elempack * out_elempack;
  201. Mat& top_blob = top_blobs[i];
  202. top_blob.create(w, h, slice / out_elempack, out_elemsize, out_elempack, opt.blob_allocator);
  203. if (top_blob.empty())
  204. return -100;
  205. q += slice;
  206. }
  207. size_t out_elemsize = top_blobs[0].elemsize;
  208. int out_elempack = top_blobs[0].elempack;
  209. for (size_t i = 0; i < top_blobs.size(); i++)
  210. {
  211. out_elemsize = std::min(out_elemsize, top_blobs[i].elemsize);
  212. out_elempack = std::min(out_elempack, top_blobs[i].elempack);
  213. }
  214. Mat bottom_blob_unpacked = bottom_blob;
  215. if (elempack > out_elempack)
  216. {
  217. convert_packing(bottom_blob, bottom_blob_unpacked, out_elempack, opt);
  218. }
  219. int p = 0;
  220. for (size_t i = 0; i < top_blobs.size(); i++)
  221. {
  222. Mat& top_blob = top_blobs[i];
  223. if (out_elempack == 1 && top_blob.elempack == 4)
  224. {
  225. int size = top_blob.w * top_blob.h;
  226. for (int q = 0; q < top_blob.c; q++)
  227. {
  228. const float* r0 = bottom_blob_unpacked.channel(p);
  229. const float* r1 = bottom_blob_unpacked.channel(p + 1);
  230. const float* r2 = bottom_blob_unpacked.channel(p + 2);
  231. const float* r3 = bottom_blob_unpacked.channel(p + 3);
  232. float* outptr0 = top_blob.channel(q);
  233. for (int j = 0; j < size; j++)
  234. {
  235. outptr0[0] = *r0++;
  236. outptr0[1] = *r1++;
  237. outptr0[2] = *r2++;
  238. outptr0[3] = *r3++;
  239. outptr0 += 4;
  240. }
  241. p += 4;
  242. }
  243. }
  244. else // if (out_elempack == 1 && top_blob.elempack == 1) if (out_elempack == 4 && top_blob.elempack == 4)
  245. {
  246. int size = top_blob.total();
  247. const float* ptr = bottom_blob_unpacked.channel(p);
  248. float* outptr = top_blob;
  249. memcpy(outptr, ptr, size * top_blob.elemsize);
  250. p += top_blob.c;
  251. }
  252. }
  253. }
  254. if (dims == 3 && positive_axis == 1)
  255. {
  256. // slice dim height
  257. int w = bottom_blob.w;
  258. int h = bottom_blob.h;
  259. int channels = bottom_blob.c;
  260. int q = 0;
  261. for (size_t i = 0; i < top_blobs.size(); i++)
  262. {
  263. int slice = slices_ptr[i];
  264. if (slice == -233)
  265. {
  266. slice = (h - q) / (top_blobs.size() - i);
  267. }
  268. Mat& top_blob = top_blobs[i];
  269. top_blob.create(w, slice, channels, elemsize, elempack, opt.blob_allocator);
  270. if (top_blob.empty())
  271. return -100;
  272. q += slice;
  273. }
  274. #pragma omp parallel for num_threads(opt.num_threads)
  275. for (int p = 0; p < channels; p++)
  276. {
  277. const float* ptr = bottom_blob.channel(p);
  278. for (size_t i = 0; i < top_blobs.size(); i++)
  279. {
  280. Mat& top_blob = top_blobs[i];
  281. int size = top_blob.w * top_blob.h;
  282. float* outptr = top_blob.channel(p);
  283. memcpy(outptr, ptr, size * elemsize);
  284. ptr += size * elempack;
  285. }
  286. }
  287. }
  288. if (dims == 3 && positive_axis == 2)
  289. {
  290. // slice dim width
  291. int w = bottom_blob.w;
  292. int h = bottom_blob.h;
  293. int channels = bottom_blob.c;
  294. int q = 0;
  295. for (size_t i = 0; i < top_blobs.size(); i++)
  296. {
  297. int slice = slices_ptr[i];
  298. if (slice == -233)
  299. {
  300. slice = (w - q) / (top_blobs.size() - i);
  301. }
  302. Mat& top_blob = top_blobs[i];
  303. top_blob.create(slice, h, channels, elemsize, elempack, opt.blob_allocator);
  304. if (top_blob.empty())
  305. return -100;
  306. q += slice;
  307. }
  308. #pragma omp parallel for num_threads(opt.num_threads)
  309. for (int p = 0; p < channels; p++)
  310. {
  311. const float* ptr = bottom_blob.channel(p);
  312. for (int j = 0; j < h; j++)
  313. {
  314. for (size_t i = 0; i < top_blobs.size(); i++)
  315. {
  316. Mat& top_blob = top_blobs[i];
  317. float* outptr = top_blob.channel(p).row(j);
  318. memcpy(outptr, ptr, top_blob.w * elemsize);
  319. ptr += top_blob.w * elempack;
  320. }
  321. }
  322. }
  323. }
  324. return 0;
  325. }
  326. int Slice_arm::forward_bf16s_fp16s(const std::vector<Mat>& bottom_blobs, std::vector<Mat>& top_blobs, const Option& opt) const
  327. {
  328. const Mat& bottom_blob = bottom_blobs[0];
  329. int dims = bottom_blob.dims;
  330. size_t elemsize = bottom_blob.elemsize;
  331. int elempack = bottom_blob.elempack;
  332. const int* slices_ptr = slices;
  333. int positive_axis = axis < 0 ? dims + axis : axis;
  334. if (dims == 1) // positive_axis == 0
  335. {
  336. // slice vector
  337. int w = bottom_blob.w * elempack;
  338. int q = 0;
  339. for (size_t i = 0; i < top_blobs.size(); i++)
  340. {
  341. int slice = slices_ptr[i];
  342. if (slice == -233)
  343. {
  344. slice = (w - q) / (top_blobs.size() - i);
  345. }
  346. int out_elempack = 1;
  347. #if __ARM_NEON
  348. if (opt.use_packing_layout)
  349. {
  350. #if __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
  351. out_elempack = opt.use_fp16_arithmetic && slice % 8 == 0 ? 8 : slice % 4 == 0 ? 4 : 1;
  352. #else
  353. out_elempack = slice % 4 == 0 ? 4 : 1;
  354. #endif
  355. }
  356. #endif
  357. size_t out_elemsize = elemsize / elempack * out_elempack;
  358. Mat& top_blob = top_blobs[i];
  359. top_blob.create(slice / out_elempack, out_elemsize, out_elempack, opt.blob_allocator);
  360. if (top_blob.empty())
  361. return -100;
  362. const unsigned short* ptr = (const unsigned short*)bottom_blob + q;
  363. unsigned short* outptr = top_blob;
  364. memcpy(outptr, ptr, top_blob.w * top_blob.elemsize);
  365. q += slice;
  366. }
  367. }
  368. if (dims == 2 && positive_axis == 0)
  369. {
  370. // slice image height
  371. int w = bottom_blob.w;
  372. int h = bottom_blob.h * elempack;
  373. int q = 0;
  374. for (size_t i = 0; i < top_blobs.size(); i++)
  375. {
  376. int slice = slices_ptr[i];
  377. if (slice == -233)
  378. {
  379. slice = (h - q) / (top_blobs.size() - i);
  380. }
  381. int out_elempack = 1;
  382. #if __ARM_NEON
  383. if (opt.use_packing_layout)
  384. {
  385. #if __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
  386. out_elempack = opt.use_fp16_arithmetic && slice % 8 == 0 ? 8 : slice % 4 == 0 ? 4 : 1;
  387. #else
  388. out_elempack = slice % 4 == 0 ? 4 : 1;
  389. #endif
  390. }
  391. #endif
  392. size_t out_elemsize = elemsize / elempack * out_elempack;
  393. Mat& top_blob = top_blobs[i];
  394. top_blob.create(w, slice / out_elempack, out_elemsize, out_elempack, opt.blob_allocator);
  395. if (top_blob.empty())
  396. return -100;
  397. q += slice;
  398. }
  399. size_t out_elemsize = top_blobs[0].elemsize;
  400. int out_elempack = top_blobs[0].elempack;
  401. for (size_t i = 0; i < top_blobs.size(); i++)
  402. {
  403. out_elemsize = std::min(out_elemsize, top_blobs[i].elemsize);
  404. out_elempack = std::min(out_elempack, top_blobs[i].elempack);
  405. }
  406. Mat bottom_blob_unpacked = bottom_blob;
  407. if (elempack > out_elempack)
  408. {
  409. convert_packing(bottom_blob, bottom_blob_unpacked, out_elempack, opt);
  410. }
  411. const unsigned short* ptr = bottom_blob_unpacked;
  412. for (size_t i = 0; i < top_blobs.size(); i++)
  413. {
  414. Mat& top_blob = top_blobs[i];
  415. #if __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
  416. if (out_elempack == 4 && top_blob.elempack == 8)
  417. {
  418. for (int j = 0; j < top_blob.h; j++)
  419. {
  420. const unsigned short* r0 = ptr;
  421. const unsigned short* r1 = ptr + w * 4;
  422. unsigned short* outptr0 = top_blob.row<unsigned short>(j);
  423. for (int j = 0; j < w; j++)
  424. {
  425. outptr0[0] = r0[0];
  426. outptr0[1] = r0[1];
  427. outptr0[2] = r0[2];
  428. outptr0[3] = r0[3];
  429. outptr0[4] = r1[0];
  430. outptr0[5] = r1[1];
  431. outptr0[6] = r1[2];
  432. outptr0[7] = r1[3];
  433. r0 += 4;
  434. r1 += 4;
  435. outptr0 += 8;
  436. }
  437. ptr += w * 8;
  438. }
  439. }
  440. if (out_elempack == 1 && top_blob.elempack == 8)
  441. {
  442. for (int j = 0; j < top_blob.h; j++)
  443. {
  444. const unsigned short* r0 = ptr;
  445. const unsigned short* r1 = ptr + w;
  446. const unsigned short* r2 = ptr + w * 2;
  447. const unsigned short* r3 = ptr + w * 3;
  448. const unsigned short* r4 = ptr + w * 4;
  449. const unsigned short* r5 = ptr + w * 5;
  450. const unsigned short* r6 = ptr + w * 6;
  451. const unsigned short* r7 = ptr + w * 7;
  452. unsigned short* outptr0 = top_blob.row<unsigned short>(j);
  453. for (int j = 0; j < w; j++)
  454. {
  455. outptr0[0] = *r0++;
  456. outptr0[1] = *r1++;
  457. outptr0[2] = *r2++;
  458. outptr0[3] = *r3++;
  459. outptr0[4] = *r4++;
  460. outptr0[5] = *r5++;
  461. outptr0[6] = *r6++;
  462. outptr0[7] = *r7++;
  463. outptr0 += 8;
  464. }
  465. ptr += w * 8;
  466. }
  467. }
  468. #endif // __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
  469. if (out_elempack == 1 && top_blob.elempack == 4)
  470. {
  471. for (int j = 0; j < top_blob.h; j++)
  472. {
  473. const unsigned short* r0 = ptr;
  474. const unsigned short* r1 = ptr + w;
  475. const unsigned short* r2 = ptr + w * 2;
  476. const unsigned short* r3 = ptr + w * 3;
  477. unsigned short* outptr0 = top_blob.row<unsigned short>(j);
  478. for (int j = 0; j < w; j++)
  479. {
  480. outptr0[0] = *r0++;
  481. outptr0[1] = *r1++;
  482. outptr0[2] = *r2++;
  483. outptr0[3] = *r3++;
  484. outptr0 += 4;
  485. }
  486. ptr += w * 4;
  487. }
  488. }
  489. if (out_elempack == top_blob.elempack) // 1-1 4-4 8-8
  490. {
  491. int size = w * top_blob.h;
  492. unsigned short* outptr = top_blob;
  493. memcpy(outptr, ptr, size * top_blob.elemsize);
  494. ptr += size * top_blob.elempack;
  495. }
  496. }
  497. }
  498. if (dims == 2 && positive_axis == 1)
  499. {
  500. // slice image width
  501. int w = bottom_blob.w;
  502. int h = bottom_blob.h;
  503. int q = 0;
  504. for (size_t i = 0; i < top_blobs.size(); i++)
  505. {
  506. int slice = slices_ptr[i];
  507. if (slice == -233)
  508. {
  509. slice = (w - q) / (top_blobs.size() - i);
  510. }
  511. Mat& top_blob = top_blobs[i];
  512. top_blob.create(slice, h, elemsize, elempack, opt.blob_allocator);
  513. if (top_blob.empty())
  514. return -100;
  515. q += slice;
  516. }
  517. #pragma omp parallel for num_threads(opt.num_threads)
  518. for (int j = 0; j < h; j++)
  519. {
  520. const unsigned short* ptr = bottom_blob.row<const unsigned short>(j);
  521. for (size_t i = 0; i < top_blobs.size(); i++)
  522. {
  523. Mat& top_blob = top_blobs[i];
  524. unsigned short* outptr = top_blob.row<unsigned short>(j);
  525. memcpy(outptr, ptr, top_blob.w * elemsize);
  526. ptr += top_blob.w * elempack;
  527. }
  528. }
  529. }
  530. if (dims == 3 && positive_axis == 0)
  531. {
  532. // slice dim channel
  533. int w = bottom_blob.w;
  534. int h = bottom_blob.h;
  535. int channels = bottom_blob.c * elempack;
  536. int q = 0;
  537. for (size_t i = 0; i < top_blobs.size(); i++)
  538. {
  539. int slice = slices_ptr[i];
  540. if (slice == -233)
  541. {
  542. slice = (channels - q) / (top_blobs.size() - i);
  543. }
  544. int out_elempack = 1;
  545. #if __ARM_NEON
  546. if (opt.use_packing_layout)
  547. {
  548. #if __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
  549. out_elempack = opt.use_fp16_arithmetic && slice % 8 == 0 ? 8 : slice % 4 == 0 ? 4 : 1;
  550. #else
  551. out_elempack = slice % 4 == 0 ? 4 : 1;
  552. #endif
  553. }
  554. #endif
  555. size_t out_elemsize = elemsize / elempack * out_elempack;
  556. Mat& top_blob = top_blobs[i];
  557. top_blob.create(w, h, slice / out_elempack, out_elemsize, out_elempack, opt.blob_allocator);
  558. if (top_blob.empty())
  559. return -100;
  560. q += slice;
  561. }
  562. size_t out_elemsize = top_blobs[0].elemsize;
  563. int out_elempack = top_blobs[0].elempack;
  564. for (size_t i = 0; i < top_blobs.size(); i++)
  565. {
  566. out_elemsize = std::min(out_elemsize, top_blobs[i].elemsize);
  567. out_elempack = std::min(out_elempack, top_blobs[i].elempack);
  568. }
  569. Mat bottom_blob_unpacked = bottom_blob;
  570. if (elempack > out_elempack)
  571. {
  572. convert_packing(bottom_blob, bottom_blob_unpacked, out_elempack, opt);
  573. }
  574. int p = 0;
  575. for (size_t i = 0; i < top_blobs.size(); i++)
  576. {
  577. Mat& top_blob = top_blobs[i];
  578. #if __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
  579. if (out_elempack == 4 && top_blob.elempack == 8)
  580. {
  581. int size = top_blob.w * top_blob.h;
  582. for (int q = 0; q < top_blob.c; q++)
  583. {
  584. const unsigned short* r0 = bottom_blob_unpacked.channel(p);
  585. const unsigned short* r1 = bottom_blob_unpacked.channel(p + 1);
  586. unsigned short* outptr0 = top_blob.channel(q);
  587. for (int j = 0; j < size; j++)
  588. {
  589. outptr0[0] = r0[0];
  590. outptr0[1] = r0[1];
  591. outptr0[2] = r0[2];
  592. outptr0[3] = r0[3];
  593. outptr0[4] = r1[0];
  594. outptr0[5] = r1[1];
  595. outptr0[6] = r1[2];
  596. outptr0[7] = r1[3];
  597. r0 += 4;
  598. r1 += 4;
  599. outptr0 += 8;
  600. }
  601. p += 2;
  602. }
  603. }
  604. if (out_elempack == 1 && top_blob.elempack == 8)
  605. {
  606. int size = top_blob.w * top_blob.h;
  607. for (int q = 0; q < top_blob.c; q++)
  608. {
  609. const unsigned short* r0 = bottom_blob_unpacked.channel(p);
  610. const unsigned short* r1 = bottom_blob_unpacked.channel(p + 1);
  611. const unsigned short* r2 = bottom_blob_unpacked.channel(p + 2);
  612. const unsigned short* r3 = bottom_blob_unpacked.channel(p + 3);
  613. const unsigned short* r4 = bottom_blob_unpacked.channel(p + 4);
  614. const unsigned short* r5 = bottom_blob_unpacked.channel(p + 5);
  615. const unsigned short* r6 = bottom_blob_unpacked.channel(p + 6);
  616. const unsigned short* r7 = bottom_blob_unpacked.channel(p + 7);
  617. unsigned short* outptr0 = top_blob.channel(q);
  618. for (int j = 0; j < size; j++)
  619. {
  620. outptr0[0] = *r0++;
  621. outptr0[1] = *r1++;
  622. outptr0[2] = *r2++;
  623. outptr0[3] = *r3++;
  624. outptr0[4] = *r4++;
  625. outptr0[5] = *r5++;
  626. outptr0[6] = *r6++;
  627. outptr0[7] = *r7++;
  628. outptr0 += 8;
  629. }
  630. p += 8;
  631. }
  632. }
  633. #endif // __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
  634. if (out_elempack == 1 && top_blob.elempack == 4)
  635. {
  636. int size = top_blob.w * top_blob.h;
  637. for (int q = 0; q < top_blob.c; q++)
  638. {
  639. const unsigned short* r0 = bottom_blob_unpacked.channel(p);
  640. const unsigned short* r1 = bottom_blob_unpacked.channel(p + 1);
  641. const unsigned short* r2 = bottom_blob_unpacked.channel(p + 2);
  642. const unsigned short* r3 = bottom_blob_unpacked.channel(p + 3);
  643. unsigned short* outptr0 = top_blob.channel(q);
  644. for (int j = 0; j < size; j++)
  645. {
  646. outptr0[0] = *r0++;
  647. outptr0[1] = *r1++;
  648. outptr0[2] = *r2++;
  649. outptr0[3] = *r3++;
  650. outptr0 += 4;
  651. }
  652. p += 4;
  653. }
  654. }
  655. if (out_elempack == top_blob.elempack) // 1-1 4-4 8-8
  656. {
  657. int size = top_blob.total();
  658. const unsigned short* ptr = bottom_blob_unpacked.channel(p);
  659. unsigned short* outptr = top_blob;
  660. memcpy(outptr, ptr, size * top_blob.elemsize);
  661. p += top_blob.c;
  662. }
  663. }
  664. }
  665. if (dims == 3 && positive_axis == 1)
  666. {
  667. // slice dim height
  668. int w = bottom_blob.w;
  669. int h = bottom_blob.h;
  670. int channels = bottom_blob.c;
  671. int q = 0;
  672. for (size_t i = 0; i < top_blobs.size(); i++)
  673. {
  674. int slice = slices_ptr[i];
  675. if (slice == -233)
  676. {
  677. slice = (h - q) / (top_blobs.size() - i);
  678. }
  679. Mat& top_blob = top_blobs[i];
  680. top_blob.create(w, slice, channels, elemsize, elempack, opt.blob_allocator);
  681. if (top_blob.empty())
  682. return -100;
  683. q += slice;
  684. }
  685. #pragma omp parallel for num_threads(opt.num_threads)
  686. for (int p = 0; p < channels; p++)
  687. {
  688. const unsigned short* ptr = bottom_blob.channel(p);
  689. for (size_t i = 0; i < top_blobs.size(); i++)
  690. {
  691. Mat& top_blob = top_blobs[i];
  692. int size = top_blob.w * top_blob.h;
  693. unsigned short* outptr = top_blob.channel(p);
  694. memcpy(outptr, ptr, size * elemsize);
  695. ptr += size * elempack;
  696. }
  697. }
  698. }
  699. if (dims == 3 && positive_axis == 2)
  700. {
  701. // slice dim width
  702. int w = bottom_blob.w;
  703. int h = bottom_blob.h;
  704. int channels = bottom_blob.c;
  705. int q = 0;
  706. for (size_t i = 0; i < top_blobs.size(); i++)
  707. {
  708. int slice = slices_ptr[i];
  709. if (slice == -233)
  710. {
  711. slice = (w - q) / (top_blobs.size() - i);
  712. }
  713. Mat& top_blob = top_blobs[i];
  714. top_blob.create(slice, h, channels, elemsize, elempack, opt.blob_allocator);
  715. if (top_blob.empty())
  716. return -100;
  717. q += slice;
  718. }
  719. #pragma omp parallel for num_threads(opt.num_threads)
  720. for (int p = 0; p < channels; p++)
  721. {
  722. const unsigned short* ptr = bottom_blob.channel(p);
  723. for (int j = 0; j < h; j++)
  724. {
  725. for (size_t i = 0; i < top_blobs.size(); i++)
  726. {
  727. Mat& top_blob = top_blobs[i];
  728. unsigned short* outptr = top_blob.channel(p).row<unsigned short>(j);
  729. memcpy(outptr, ptr, top_blob.w * elemsize);
  730. ptr += top_blob.w * elempack;
  731. }
  732. }
  733. }
  734. }
  735. return 0;
  736. }
  737. } // namespace ncnn