Expression Templates Library (ETL)
avg_pooling_derivative.hpp
1 //=======================================================================
2 // Copyright (c) 2014-2023 Baptiste Wicht
3 // Distributed under the terms of the MIT License.
4 // (See accompanying file LICENSE or copy at
5 // http://opensource.org/licenses/MIT)
6 //=======================================================================
7 
8 #pragma once
9 
10 namespace etl::impl {
11 
26  template <size_t C1, size_t C2, size_t S1, size_t S2, size_t P1, size_t P2, typename A, typename B, typename M>
27  static void pool_derivative_block([[maybe_unused]] const A& in, [[maybe_unused]] const B& out, M& m, size_t j, size_t k) {
28  // Slow path for cells with padding
29  if constexpr (P1 || P2) {
30  if (cpp_unlikely(j < P1 || k < P2 || j >= etl::dim<0>(out) - P1 || k >= etl::dim<1>(out) - P2)) {
31  const size_t base_j = j * S1 - P1;
32  const size_t base_k = k * S2 - P2;
33 
34  for (size_t jj = 0; jj < C1; ++jj) {
35  for (size_t kk = 0; kk < C2; ++kk) {
36  if (base_j + jj < etl::dim<0>(m) && base_k + kk < etl::dim<1>(m)) {
37  m(base_j + jj, base_k + kk) = value_t<A>(1) / value_t<A>(C1 * C2);
38  }
39  }
40  }
41 
42  return;
43  }
44  }
45 
46  for (size_t jj = 0; jj < C1; ++jj) {
47  for (size_t kk = 0; kk < C2; ++kk) {
48  if constexpr ((C1 == S1 && C2 == S2) || cudnn_compatible) {
49  m(j * S1 - P1 + jj, k * S2 - P2 + kk) = value_t<A>(1) / value_t<A>(C1 * C2);
50  } else {
51  m(j * S1 - P1 + jj, k * S2 - P2 + kk) += value_t<A>(1) / value_t<A>(C1 * C2);
52  }
53  }
54  }
55  }
56 
65  template <size_t C1, size_t C2, size_t C3, size_t S1, size_t S2, size_t S3, size_t P1, size_t P2, size_t P3, etl_2d A, typename B, typename M>
66  static void apply(A&& in, B&& out, M&& m) {
67  in.ensure_cpu_up_to_date();
68  out.ensure_cpu_up_to_date();
69 
70  if constexpr (!cudnn_compatible && (C1 != S1 || C2 != S2)) {
71  m = 0;
72  }
73 
74  for (size_t j = 0; j < etl::dim<0>(out); ++j) {
75  for (size_t k = 0; k < etl::dim<1>(out); ++k) {
76  pool_derivative_block<C1, C2, S1, S2, P1, P2>(in, out, m, j, k);
77  }
78  }
79 
80  m.invalidate_gpu();
81  m.validate_cpu();
82  }
83 
94  template <typename A, typename B, typename M>
95  static void pool_derivative_block(
96  [[maybe_unused]] const A& in, [[maybe_unused]] const B& out, M& m, size_t j, size_t k, size_t c1, size_t c2, size_t s1, size_t s2, size_t p1, size_t p2) {
97  // Slow path for cells with padding
98  if (cpp_unlikely(p1 || p2)) {
99  if (cpp_unlikely(j < p1 || k < p2 || j >= etl::dim<0>(out) - p1 || k >= etl::dim<1>(out) - p2)) {
100  const size_t base_j = j * s1 - p1;
101  const size_t base_k = k * s2 - p2;
102 
103  for (size_t jj = 0; jj < c1; ++jj) {
104  for (size_t kk = 0; kk < c2; ++kk) {
105  if (base_j + jj < etl::dim<0>(m) && base_k + kk < etl::dim<1>(m)) {
106  m(base_j + jj, base_k + kk) = value_t<A>(1) / value_t<A>(c1 * c2);
107  }
108  }
109  }
110 
111  return;
112  }
113  }
114 
115  if ((c1 == s1 && c2 == s2) || cudnn_compatible) {
116  for (size_t jj = 0; jj < c1; ++jj) {
117  for (size_t kk = 0; kk < c2; ++kk) {
118  m(j * s1 - p1 + jj, k * s2 - p2 + kk) = value_t<A>(1) / value_t<A>(c1 * c2);
119  }
120  }
121  } else {
122  for (size_t jj = 0; jj < c1; ++jj) {
123  for (size_t kk = 0; kk < c2; ++kk) {
124  m(j * s1 - p1 + jj, k * s2 - p2 + kk) += value_t<A>(1) / value_t<A>(c1 * c2);
125  }
126  }
127  }
128  }
129 
138  template <etl_2d A, typename B, typename M>
139  static void apply(A&& in, B&& out, M&& m, size_t c1, size_t c2, [[maybe_unused]] size_t c3, size_t s1, size_t s2, [[maybe_unused]] size_t s3, size_t p1, size_t p2, [[maybe_unused]] size_t p3) {
140  in.ensure_cpu_up_to_date();
141  out.ensure_cpu_up_to_date();
142 
143  if (!cudnn_compatible && (c1 != s1 || c2 != s2)) {
144  m = 0;
145  }
146 
147  for (size_t j = 0; j < etl::dim<0>(out); ++j) {
148  for (size_t k = 0; k < etl::dim<1>(out); ++k) {
149  pool_derivative_block(in, out, m, j, k, c1, c2, s1, s2, p1, p2);
150  }
151  }
152 
153  m.invalidate_gpu();
154  m.validate_cpu();
155  }
156 
157  // Deep handling
158 
167  template <size_t C1, size_t C2, size_t C3, size_t S1, size_t S2, size_t S3, size_t P1, size_t P2, size_t P3, deep_mat A, typename B, typename M>
168  static void apply(A&& in, B&& out, M& m) {
169  in.ensure_cpu_up_to_date();
170  out.ensure_cpu_up_to_date();
171 
172  for (size_t i = 0; i < etl::dim<0>(in); ++i) {
173  apply<C1, C2, C3, S1, S2, S3, P1, P2, P3>(in(i), out(i), m(i));
174  }
175 
176  m.invalidate_gpu();
177  m.validate_cpu();
178  }
179 
188  template <deep_mat A, typename B, typename M>
189  static void apply(A&& in, B&& out, M& m, size_t c1, size_t c2, size_t c3, size_t s1, size_t s2, size_t s3, size_t p1, size_t p2, size_t p3) {
190  in.ensure_cpu_up_to_date();
191  out.ensure_cpu_up_to_date();
192 
193  for (size_t i = 0; i < etl::dim<0>(in); ++i) {
194  apply(in(i), out(i), m(i), c1, c2, c3, s1, s2, s3, p1, p2, p3);
195  }
196 
197  m.invalidate_gpu();
198  m.validate_cpu();
199  }
200 };
201 
218  template <size_t C1, size_t C2, size_t C3, size_t S1, size_t S2, size_t S3, size_t P1, size_t P2, size_t P3, typename A, typename B, typename M>
219  static void pool_derivative_block([[maybe_unused]] const A& in, [[maybe_unused]] const B& out, M& m, size_t i, size_t j, size_t k) {
220  for (size_t ii = 0; ii < C1; ++ii) {
221  for (size_t jj = 0; jj < C2; ++jj) {
222  for (size_t kk = 0; kk < C3; ++kk) {
223  m(i * C1 + ii, j * C2 + jj, k * C3 + kk) = value_t<A>(1) / value_t<A>(C1 * C2 * C3);
224  }
225  }
226  }
227  }
228 
237  template <size_t C1, size_t C2, size_t C3, size_t S1, size_t S2, size_t S3, size_t P1, size_t P2, size_t P3, etl_3d A, typename B, typename M>
238  static void apply(A&& in, B&& out, M&& m) {
239  in.ensure_cpu_up_to_date();
240  out.ensure_cpu_up_to_date();
241 
242  for (size_t i = 0; i < etl::dim<0>(out); ++i) {
243  for (size_t j = 0; j < etl::dim<1>(out); ++j) {
244  for (size_t k = 0; k < etl::dim<2>(out); ++k) {
245  pool_derivative_block<C1, C2, C3, S1, S2, S3, P1, P2, P3>(in, out, m, i, j, k);
246  }
247  }
248  }
249 
250  m.invalidate_gpu();
251  m.validate_cpu();
252  }
253 
266  template <typename A, typename B, typename M>
267  static void pool_derivative_block([[maybe_unused]] const A& in,
268  [[maybe_unused]] const B& out,
269  M& m,
270  size_t i,
271  size_t j,
272  size_t k,
273  size_t c1,
274  size_t c2,
275  size_t c3,
276  [[maybe_unused]] size_t s1,
277  [[maybe_unused]] size_t s2,
278  [[maybe_unused]] size_t s3,
279  [[maybe_unused]] size_t p1,
280  [[maybe_unused]] size_t p2,
281  [[maybe_unused]] size_t p3) {
282  for (size_t ii = 0; ii < c1; ++ii) {
283  for (size_t jj = 0; jj < c2; ++jj) {
284  for (size_t kk = 0; kk < c3; ++kk) {
285  m(i * c1 + ii, j * c2 + jj, k * c3 + kk) = value_t<A>(1) / value_t<A>(c1 * c2 * c3);
286  }
287  }
288  }
289  }
290 
299  template <etl_3d A, typename B, typename M>
300  static void apply(A&& in, B&& out, M&& m, size_t c1, size_t c2, size_t c3, size_t s1, size_t s2, size_t s3, size_t p1, size_t p2, size_t p3) {
301  in.ensure_cpu_up_to_date();
302  out.ensure_cpu_up_to_date();
303 
304  for (size_t i = 0; i < etl::dim<0>(out); ++i) {
305  for (size_t j = 0; j < etl::dim<1>(out); ++j) {
306  for (size_t k = 0; k < etl::dim<2>(out); ++k) {
307  pool_derivative_block(in, out, m, i, j, k, c1, c2, c3, s1, s2, s3, p1, p2, p3);
308  }
309  }
310  }
311 
312  m.invalidate_gpu();
313  m.validate_cpu();
314  }
315 
316  // Deep handling
317 
326  template <size_t C1, size_t C2, size_t C3, size_t S1, size_t S2, size_t S3, size_t P1, size_t P2, size_t P3, etl_4d_and_plus A, typename B, typename M>
327  static void apply(A&& in, B&& out, M& m) {
328  in.ensure_cpu_up_to_date();
329  out.ensure_cpu_up_to_date();
330 
331  for (size_t i = 0; i < etl::dim<0>(in); ++i) {
332  apply<C1, C2, C3, S1, S2, S3, P1, P2, P3>(in(i), out(i), m(i));
333  }
334 
335  m.invalidate_gpu();
336  m.validate_cpu();
337  }
338 
347  template <etl_4d_and_plus A, typename B, typename M>
348  static void apply(
349  A&& in, B&& out, M& m, size_t c1, size_t c2, size_t c3, size_t s1, size_t s2, size_t s3, size_t p1, size_t p2, size_t p3) {
350  in.ensure_cpu_up_to_date();
351  out.ensure_cpu_up_to_date();
352 
353  for (size_t i = 0; i < etl::dim<0>(in); ++i) {
354  apply(in(i), out(i), m(i), c1, c2, c3, s1, s2, s3, p1, p2, p3);
355  }
356 
357  m.invalidate_gpu();
358  m.validate_cpu();
359  }
360 };
361 
362 } //end of namespace etl::impl
static void apply(A &&in, B &&out, M &m)
Apply the functor on sub and store the result in m.
Definition: avg_pooling_derivative.hpp:168
static void apply(A &&in, B &&out, M &m, size_t c1, size_t c2, size_t c3, size_t s1, size_t s2, size_t s3, size_t p1, size_t p2, size_t p3)
Apply the functor on sub and store the result in m.
Definition: avg_pooling_derivative.hpp:189
static void apply(A &&in, B &&out, M &m, size_t c1, size_t c2, size_t c3, size_t s1, size_t s2, size_t s3, size_t p1, size_t p2, size_t p3)
Apply the functor on sub and store the result in m.
Definition: avg_pooling_derivative.hpp:348
static void pool_derivative_block([[maybe_unused]] const A &in, [[maybe_unused]] const B &out, M &m, size_t i, size_t j, size_t k)
Pool a block of the sub expression.
Definition: avg_pooling_derivative.hpp:219
static void apply(A &&in, B &&out, M &m)
Apply the functor on sub and store the result in m.
Definition: avg_pooling_derivative.hpp:327
Functor for the derivative of 2D Avg Pooling.
Definition: avg_pooling_derivative.hpp:15
static void apply(A &&in, B &&out, M &&m)
Apply the functor on sub and store the result in m.
Definition: avg_pooling_derivative.hpp:66
static void pool_derivative_block([[maybe_unused]] const A &in, [[maybe_unused]] const B &out, M &m, size_t i, size_t j, size_t k, size_t c1, size_t c2, size_t c3, [[maybe_unused]] size_t s1, [[maybe_unused]] size_t s2, [[maybe_unused]] size_t s3, [[maybe_unused]] size_t p1, [[maybe_unused]] size_t p2, [[maybe_unused]] size_t p3)
Pool a block of the sub expression.
Definition: avg_pooling_derivative.hpp:267
static void apply(A &&in, B &&out, M &&m, size_t c1, size_t c2, size_t c3, size_t s1, size_t s2, size_t s3, size_t p1, size_t p2, size_t p3)
Apply the functor on sub and store the result in m.
Definition: avg_pooling_derivative.hpp:300
static void apply(A &&in, B &&out, M &&m, size_t c1, size_t c2, [[maybe_unused]] size_t c3, size_t s1, size_t s2, [[maybe_unused]] size_t s3, size_t p1, size_t p2, [[maybe_unused]] size_t p3)
Apply the functor on sub and store the result in m.
Definition: avg_pooling_derivative.hpp:139
constexpr bool cudnn_compatible
Indicates if ETL is trying to generate results similar to CUDNN (default).
Definition: config.hpp:163
static void apply(A &&in, B &&out, M &&m)
Apply the functor on sub and store the result in m.
Definition: avg_pooling_derivative.hpp:238
static void pool_derivative_block([[maybe_unused]] const A &in, [[maybe_unused]] const B &out, M &m, size_t j, size_t k, size_t c1, size_t c2, size_t s1, size_t s2, size_t p1, size_t p2)
Pool a block of the sub expression.
Definition: avg_pooling_derivative.hpp:95
Definition: avg_pooling_derivative.hpp:10
typename decay_traits< E >::value_type value_t
Traits to extract the value type out of an ETL type.
Definition: tmp.hpp:81
Functor for the derivative of 3D Avg Pooling.
Definition: avg_pooling_derivative.hpp:205
static void pool_derivative_block([[maybe_unused]] const A &in, [[maybe_unused]] const B &out, M &m, size_t j, size_t k)
Pool a block of the sub expression.
Definition: avg_pooling_derivative.hpp:27