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.

eltwise.cpp 5.9 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  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 "eltwise.h"
  15. #include <algorithm>
  16. namespace ncnn {
  17. DEFINE_LAYER_CREATOR(Eltwise)
  18. Eltwise::Eltwise()
  19. {
  20. }
  21. int Eltwise::load_param(const ParamDict& pd)
  22. {
  23. op_type = pd.get(0, 0);
  24. coeffs = pd.get(1, Mat());
  25. return 0;
  26. }
  27. int Eltwise::forward(const std::vector<Mat>& bottom_blobs, std::vector<Mat>& top_blobs, const Option& opt) const
  28. {
  29. const Mat& bottom_blob = bottom_blobs[0];
  30. int w = bottom_blob.w;
  31. int h = bottom_blob.h;
  32. int channels = bottom_blob.c;
  33. size_t elemsize = bottom_blob.elemsize;
  34. int size = w * h;
  35. Mat& top_blob = top_blobs[0];
  36. top_blob.create(w, h, channels, elemsize, opt.blob_allocator);
  37. if (top_blob.empty())
  38. return -100;
  39. if (op_type == Operation_PROD)
  40. {
  41. // first blob
  42. const Mat& bottom_blob1 = bottom_blobs[1];
  43. #pragma omp parallel for num_threads(opt.num_threads)
  44. for (int q=0; q<channels; q++)
  45. {
  46. const float* ptr = bottom_blob.channel(q);
  47. const float* ptr1 = bottom_blob1.channel(q);
  48. float* outptr = top_blob.channel(q);
  49. for (int i=0; i<size; i++)
  50. {
  51. outptr[i] = ptr[i] * ptr1[i];
  52. }
  53. }
  54. for (size_t b=2; b<bottom_blobs.size(); b++)
  55. {
  56. const Mat& bottom_blob1 = bottom_blobs[b];
  57. #pragma omp parallel for num_threads(opt.num_threads)
  58. for (int q=0; q<channels; q++)
  59. {
  60. const float* ptr = bottom_blob1.channel(q);
  61. float* outptr = top_blob.channel(q);
  62. for (int i=0; i<size; i++)
  63. {
  64. outptr[i] *= ptr[i];
  65. }
  66. }
  67. }
  68. }
  69. else if (op_type == Operation_SUM)
  70. {
  71. if (coeffs.w == 0)
  72. {
  73. // first blob
  74. const Mat& bottom_blob1 = bottom_blobs[1];
  75. #pragma omp parallel for num_threads(opt.num_threads)
  76. for (int q=0; q<channels; q++)
  77. {
  78. const float* ptr = bottom_blob.channel(q);
  79. const float* ptr1 = bottom_blob1.channel(q);
  80. float* outptr = top_blob.channel(q);
  81. for (int i=0; i<size; i++)
  82. {
  83. outptr[i] = ptr[i] + ptr1[i];
  84. }
  85. }
  86. for (size_t b=2; b<bottom_blobs.size(); b++)
  87. {
  88. const Mat& bottom_blob1 = bottom_blobs[b];
  89. #pragma omp parallel for num_threads(opt.num_threads)
  90. for (int q=0; q<channels; q++)
  91. {
  92. const float* ptr = bottom_blob1.channel(q);
  93. float* outptr = top_blob.channel(q);
  94. for (int i=0; i<size; i++)
  95. {
  96. outptr[i] += ptr[i];
  97. }
  98. }
  99. }
  100. }
  101. else
  102. {
  103. // first blob
  104. const Mat& bottom_blob1 = bottom_blobs[1];
  105. float coeff0 = coeffs[0];
  106. float coeff1 = coeffs[1];
  107. #pragma omp parallel for num_threads(opt.num_threads)
  108. for (int q=0; q<channels; q++)
  109. {
  110. const float* ptr = bottom_blob.channel(q);
  111. const float* ptr1 = bottom_blob1.channel(q);
  112. float* outptr = top_blob.channel(q);
  113. for (int i=0; i<size; i++)
  114. {
  115. outptr[i] = ptr[i] * coeff0 + ptr1[i] * coeff1;
  116. }
  117. }
  118. for (size_t b=2; b<bottom_blobs.size(); b++)
  119. {
  120. const Mat& bottom_blob1 = bottom_blobs[b];
  121. float coeff = coeffs[b];
  122. #pragma omp parallel for num_threads(opt.num_threads)
  123. for (int q=0; q<channels; q++)
  124. {
  125. const float* ptr = bottom_blob1.channel(q);
  126. float* outptr = top_blob.channel(q);
  127. for (int i=0; i<size; i++)
  128. {
  129. outptr[i] += ptr[i] * coeff;
  130. }
  131. }
  132. }
  133. }
  134. }
  135. else if (op_type == Operation_MAX)
  136. {
  137. // first blob
  138. const Mat& bottom_blob1 = bottom_blobs[1];
  139. #pragma omp parallel for num_threads(opt.num_threads)
  140. for (int q=0; q<channels; q++)
  141. {
  142. const float* ptr = bottom_blob.channel(q);
  143. const float* ptr1 = bottom_blob1.channel(q);
  144. float* outptr = top_blob.channel(q);
  145. for (int i=0; i<size; i++)
  146. {
  147. outptr[i] = std::max(ptr[i], ptr1[i]);
  148. }
  149. }
  150. for (size_t b=2; b<bottom_blobs.size(); b++)
  151. {
  152. const Mat& bottom_blob1 = bottom_blobs[b];
  153. #pragma omp parallel for num_threads(opt.num_threads)
  154. for (int q=0; q<channels; q++)
  155. {
  156. const float* ptr = bottom_blob1.channel(q);
  157. float* outptr = top_blob.channel(q);
  158. for (int i=0; i<size; i++)
  159. {
  160. outptr[i] = std::max(outptr[i], ptr[i]);
  161. }
  162. }
  163. }
  164. }
  165. return 0;
  166. }
  167. } // namespace ncnn