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.

padding_arm.cpp 6.1 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  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 "padding_arm.h"
  15. #if __ARM_NEON
  16. #include <arm_neon.h>
  17. #endif // __ARM_NEON
  18. namespace ncnn {
  19. DEFINE_LAYER_CREATOR(Padding_arm)
  20. Padding_arm::Padding_arm()
  21. {
  22. #if __ARM_NEON
  23. support_packing = true;
  24. #endif // __ARM_NEON
  25. }
  26. #if __ARM_NEON
  27. static void padding_constant_pack4_neon(const Mat& src, Mat& dst, int top, int bottom, int left, int right, float v)
  28. {
  29. float32x4_t _v = vdupq_n_f32(v);
  30. const float* ptr = src;
  31. float* outptr = dst;
  32. // fill top
  33. for (int i = 0; i < top * dst.w; i++)
  34. {
  35. vst1q_f32(outptr, _v);
  36. outptr += 4;
  37. }
  38. // fill center
  39. for (int y = 0; y < src.h; y++)
  40. {
  41. for (int x = 0; x < left; x++)
  42. {
  43. vst1q_f32(outptr, _v);
  44. outptr += 4;
  45. }
  46. for (int x = 0; x < src.w; x++)
  47. {
  48. float32x4_t _p = vld1q_f32(ptr);
  49. vst1q_f32(outptr, _p);
  50. ptr += 4;
  51. outptr += 4;
  52. }
  53. for (int x = 0; x < right; x++)
  54. {
  55. vst1q_f32(outptr, _v);
  56. outptr += 4;
  57. }
  58. }
  59. // fill bottom
  60. for (int i = 0; i < bottom * dst.w; i++)
  61. {
  62. vst1q_f32(outptr, _v);
  63. outptr += 4;
  64. }
  65. }
  66. static void padding_replicate_pack4_neon(const Mat& src, Mat& dst, int top, int bottom, int left, int right)
  67. {
  68. const float* ptr = src;
  69. float* outptr = dst;
  70. // fill top
  71. for (int y = 0; y < top; y++)
  72. {
  73. const float* ptr0 = ptr;
  74. float32x4_t _p = vld1q_f32(ptr0);
  75. for (int x = 0; x < left; x++)
  76. {
  77. vst1q_f32(outptr, _p);
  78. outptr += 4;
  79. }
  80. for (int x = 0; x < src.w; x++)
  81. {
  82. _p = vld1q_f32(ptr0);
  83. vst1q_f32(outptr, _p);
  84. ptr0 += 4;
  85. outptr += 4;
  86. }
  87. for (int x = 0; x < right; x++)
  88. {
  89. vst1q_f32(outptr, _p);
  90. outptr += 4;
  91. }
  92. }
  93. // fill center
  94. for (int y = 0; y < src.h; y++)
  95. {
  96. float32x4_t _p = vld1q_f32(ptr);
  97. for (int x = 0; x < left; x++)
  98. {
  99. vst1q_f32(outptr, _p);
  100. outptr += 4;
  101. }
  102. for (int x = 0; x < src.w; x++)
  103. {
  104. _p = vld1q_f32(ptr);
  105. vst1q_f32(outptr, _p);
  106. ptr += 4;
  107. outptr += 4;
  108. }
  109. for (int x = 0; x < right; x++)
  110. {
  111. vst1q_f32(outptr, _p);
  112. outptr += 4;
  113. }
  114. }
  115. // fill bottom
  116. ptr -= src.w * 4;
  117. for (int y = 0; y < bottom; y++)
  118. {
  119. const float* ptr0 = ptr;
  120. float32x4_t _p = vld1q_f32(ptr0);
  121. for (int x = 0; x < left; x++)
  122. {
  123. vst1q_f32(outptr, _p);
  124. outptr += 4;
  125. }
  126. for (int x = 0; x < src.w; x++)
  127. {
  128. _p = vld1q_f32(ptr0);
  129. vst1q_f32(outptr, _p);
  130. ptr0 += 4;
  131. outptr += 4;
  132. }
  133. for (int x = 0; x < right; x++)
  134. {
  135. vst1q_f32(outptr, _p);
  136. outptr += 4;
  137. }
  138. }
  139. }
  140. #endif // __ARM_NEON
  141. int Padding_arm::forward(const Mat& bottom_blob, Mat& top_blob, const Option& opt) const
  142. {
  143. if (top == 0 && bottom == 0 && left == 0 && right == 0)
  144. {
  145. top_blob = bottom_blob;
  146. return 0;
  147. }
  148. int w = bottom_blob.w;
  149. int h = bottom_blob.h;
  150. int channels = bottom_blob.c;
  151. int dims = bottom_blob.dims;
  152. size_t elemsize = bottom_blob.elemsize;
  153. int elempack = bottom_blob.elempack;
  154. #if __ARM_NEON
  155. if (opt.use_packing_layout)
  156. {
  157. if (elempack == 4)
  158. {
  159. int outw = w + left + right;
  160. if (dims == 1)
  161. {
  162. top_blob.create(outw, elemsize, opt.blob_allocator);
  163. if (top_blob.empty())
  164. return -100;
  165. if (type == 0)
  166. padding_constant_pack4_neon(bottom_blob, top_blob, 0, 0, left, right, value);
  167. else
  168. padding_replicate_pack4_neon(bottom_blob, top_blob, 0, 0, left, right);
  169. return 0;
  170. }
  171. int outh = h + top + bottom;
  172. if (dims == 2)
  173. {
  174. top_blob.create(outw, outh, elemsize, opt.blob_allocator);
  175. if (top_blob.empty())
  176. return -100;
  177. if (type == 0)
  178. padding_constant_pack4_neon(bottom_blob, top_blob, top, bottom, left, right, value);
  179. else
  180. padding_replicate_pack4_neon(bottom_blob, top_blob, top, bottom, left, right);
  181. return 0;
  182. }
  183. if (dims == 3)
  184. {
  185. top_blob.create(outw, outh, channels, elemsize, opt.blob_allocator);
  186. if (top_blob.empty())
  187. return -100;
  188. #pragma omp parallel for num_threads(opt.num_threads)
  189. for (int q=0; q<channels; q++)
  190. {
  191. const Mat m = bottom_blob.channel(q);
  192. Mat borderm = top_blob.channel(q);
  193. if (type == 0)
  194. padding_constant_pack4_neon(m, borderm, top, bottom, left, right, value);
  195. else
  196. padding_replicate_pack4_neon(m, borderm, top, bottom, left, right);
  197. }
  198. return 0;
  199. }
  200. return 0;
  201. }
  202. } // opt.use_packing_layout
  203. #endif // __ARM_NEON
  204. return Padding::forward(bottom_blob, top_blob, opt);
  205. }
  206. } // namespace ncnn