2
2
# the inner loop operation and a few initialization parameters.
3
3
for name in (:max , :mean , :lpnorm )
4
4
@eval function $ ((Symbol (" $(name) pool_direct!" )))(
5
- y:: AbstractArray{T , 5} , x:: AbstractArray{T , 5} ,
6
- pdims:: PoolDims ; alpha:: T = T ( 1 ) , beta:: T = T ( 0 ) , kwargs... ) where T
5
+ y:: AbstractArray{<:Any , 5} , x:: AbstractArray{<:Any , 5} ,
6
+ pdims:: PoolDims ; alpha= 1 , beta= 0 , kwargs... )
7
7
$ ((Symbol (" $(name) pool_direct!" )))(
8
8
y, x, pdims,
9
9
Val (kernel_size (pdims)), Val (channels_out (pdims)),
@@ -13,13 +13,13 @@ for name in (:max, :mean, :lpnorm)
13
13
end
14
14
15
15
@eval function $ ((Symbol (" $(name) pool_direct!" )))(
16
- y:: AbstractArray{T,5} , x:: AbstractArray{T ,5} ,
16
+ y:: AbstractArray{T,5} , x:: AbstractArray{<:Any ,5} ,
17
17
pdims:: PoolDims ,
18
18
# kernel size, channels out, padding, dilation, stride
19
19
:: Val{K} , :: Val{C} , :: Val{P} , :: Val{D} , :: Val{S} ;
20
- alpha:: T = T ( 1 ) , beta:: T = T ( 0 ) , kwargs...
20
+ alpha= 1 , beta= 0 , kwargs...
21
21
) where {T, K, C, P, D, S}
22
- @assert beta == T ( 0 ) " beta not supported yet"
22
+ @assert iszero (beta ) " beta not supported yet"
23
23
check_dims (size (x), size (y), pdims)
24
24
25
25
width, height, depth = input_size (pdims)
@@ -36,10 +36,21 @@ for name in (:max, :mean, :lpnorm)
36
36
@inline project (idx, stride, pad) = (idx - 1 ) * stride - pad + 1
37
37
38
38
# If we're doing mean pooling, we represent division by kernel size by rolling it
39
- # into the `alpha` multiplier.
40
- if $ (name == :mean )
41
- alpha = alpha / prod (K)
39
+ # into the `alpha` multiplier.
40
+ # The type might change here, that's why we prepend the underscore
41
+ # (does it make a difference, though?)
42
+ _alpha = if $ (name == :mean )
43
+ T (alpha / prod (K))
44
+ else
45
+ T (alpha)
42
46
end
47
+ # _beta = T(beta)
48
+
49
+ # A quick note on the array element types `T` and `R`:
50
+ # Ideally, `T == R`, but in some edge-cases, this might not be the case
51
+ # (e.g. with `ReverseDiff.TrackedArray`, see issue #484).
52
+ # If the types differ, we will initialize variables (like `_alpha` above) with the
53
+ # target eltype `T`.
43
54
44
55
p = if $ (name != :lpnorm ) 0 else
45
56
! haskey (kwargs, :p ) && error (" lpnormpool needs keyword argument `p`" )
@@ -94,7 +105,7 @@ for name in (:max, :mean, :lpnorm)
94
105
# for lpnormpool, y = (∑ᵢ xᵢ^p)^(1 / p)
95
106
m = $ (name == :lpnorm ) ? m^ (T (1 ) / p) : m
96
107
97
- y[w, h, d, c, batch_idx] = alpha * m # + beta * y[w, h, d, c, batch_idx]
108
+ y[w, h, d, c, batch_idx] = _alpha * m # + _beta * y[w, h, d, c, batch_idx]
98
109
end
99
110
end
100
111
end
@@ -148,7 +159,7 @@ for name in (:max, :mean, :lpnorm)
148
159
end
149
160
end
150
161
$ (name == :lpnorm ) && (m = m^ (T (1 ) / p))
151
- y[w, h, d, c, batch_idx] = alpha * m # + beta * y[w, h, d, c, batch_idx]
162
+ y[w, h, d, c, batch_idx] = _alpha * m # + _beta * y[w, h, d, c, batch_idx]
152
163
end
153
164
end
154
165
end
@@ -159,9 +170,9 @@ for name in (:max, :mean, :lpnorm)
159
170
end
160
171
161
172
@eval function $ ((Symbol (" ∇$(name) pool_direct!" )))(
162
- dx:: AbstractArray{T ,5} , dy:: AbstractArray{T ,5} ,
163
- y:: AbstractArray{T ,5} , x:: AbstractArray{T ,5} ,
164
- pdims:: PoolDims ; kwargs... ) where T
173
+ dx:: AbstractArray{<:Any ,5} , dy:: AbstractArray{<:Any ,5} ,
174
+ y:: AbstractArray{<:Any ,5} , x:: AbstractArray{<:Any ,5} ,
175
+ pdims:: PoolDims ; kwargs... )
165
176
$ ((Symbol (" ∇$(name) pool_direct!" )))(
166
177
dx, dy, y, x, pdims, Val (kernel_size (pdims)); kwargs... )
167
178
return dx
@@ -170,10 +181,10 @@ for name in (:max, :mean, :lpnorm)
170
181
# Same story for gradients, and although this is very similar to the forward pass,
171
182
# it's unfortunately different enough that I think we need a separate function. :(
172
183
@eval function $ ((Symbol (" ∇$(name) pool_direct!" )))(
173
- dx:: AbstractArray{T,5} , dy:: AbstractArray{T ,5} ,
174
- y:: AbstractArray{T ,5} , x:: AbstractArray{T ,5} ,
184
+ dx:: AbstractArray{T,5} , dy:: AbstractArray{<:Any ,5} ,
185
+ y:: AbstractArray{<:Any ,5} , x:: AbstractArray{<:Any ,5} ,
175
186
pdims:: PoolDims , :: Val{K} ; # == kernel_size(pdims)
176
- alpha:: T = T ( 1 ) , beta:: T = T ( 0 ) , kwargs... ) where {T, K}
187
+ alpha= 1 , beta= 0 , kwargs... ) where {T, K}
177
188
check_dims (size (x), size (dy), pdims)
178
189
179
190
width, height, depth = input_size (pdims)
@@ -183,6 +194,10 @@ for name in (:max, :mean, :lpnorm)
183
194
dil_w, dil_h, dil_d = dilation (pdims)
184
195
stride_w, stride_h, stride_d = stride (pdims)
185
196
197
+ # Concerning array eltypes `DX, DY, X, Y`, we want handle them like above, i.e.,
198
+ # initialize everything with the left-hand-side type (target type).
199
+ # Of course, ideally the types are all the same anyways.
200
+
186
201
# We use calc_padding_regions to split outselves up into separate regions that
187
202
# may or may not need to worry about padding:
188
203
padded_regions, central_region = calc_padding_regions (pdims)
@@ -191,9 +206,11 @@ for name in (:max, :mean, :lpnorm)
191
206
@inline project (idx, stride, pad) = (idx - 1 ) * stride - pad + 1
192
207
193
208
# If we're doing mean pooling, we represent division by kernel size by rolling
194
- # it into the `alpha` multiplier.
195
- if $ (name == :mean )
196
- alpha = alpha / prod (K)
209
+ # it into the `_alpha` multiplier.
210
+ _alpha = if $ (name == :mean )
211
+ T (alpha / prod (K))
212
+ else
213
+ T (alpha)
197
214
end
198
215
199
216
p = if $ (name != :lpnorm ) 0 else
@@ -236,15 +253,15 @@ for name in (:max, :mean, :lpnorm)
236
253
# Uncomment line below if using with non-precise output (e.g. by NNPACK)
237
254
# if abs(y_idx - x[x_idxs...]) < 1e-5 && !maxpool_already_chose
238
255
if y_idx ≈ x[input_kw, input_kh, input_kd, c, batch_idx]
239
- dx[input_kw, input_kh, input_kd, c, batch_idx] += dy_idx * alpha # + beta * dx[x_idxs...]
256
+ dx[input_kw, input_kh, input_kd, c, batch_idx] += dy_idx * _alpha # + _beta * dx[x_idxs...]
240
257
maxpool_already_chose = true
241
258
# Maxpooling does not support `beta` right now. :(
242
259
# else
243
260
# dx[x_idxs...] = T(0) + beta*dx[x_idxs...]
244
261
end
245
262
elseif $ (name == :mean )
246
263
# Either does meanpool :(
247
- dx[input_kw, input_kh, input_kd, c, batch_idx] += dy_idx * alpha
264
+ dx[input_kw, input_kh, input_kd, c, batch_idx] += dy_idx * _alpha
248
265
elseif $ (name == :lpnorm )
249
266
# y = (∑ᵢ xᵢ^p)^(1 / p), ∂y/∂xᵢ = xᵢ^(p-1) × y^(1-p)
250
267
grad = x[input_kw, input_kh, input_kd, c, batch_idx]^ (p- 1 ) * y_idx^ (1 - p)
@@ -302,13 +319,13 @@ for name in (:max, :mean, :lpnorm)
302
319
# Uncomment line below if using with non-precise output
303
320
# if abs(y_idx - x[x_idxs...]) < 1e-5 && !maxpool_already_chose
304
321
if y_idx ≈ x[input_kw, input_kh, input_kd, c, batch_idx]
305
- dx[input_kw, input_kh, input_kd, c, batch_idx] += dy_idx * alpha # + beta * dx[x_idxs...]
322
+ dx[input_kw, input_kh, input_kd, c, batch_idx] += dy_idx * _alpha # + _beta * dx[x_idxs...]
306
323
maxpool_already_chose = true
307
324
# else
308
325
# dx[x_idxs...] = T(0) + beta*dx[x_idxs...]
309
326
end
310
327
elseif $ (name == :mean )
311
- dx[input_kw, input_kh, input_kd, c, batch_idx] += dy_idx * alpha # + beta * dx[x_idxs...]
328
+ dx[input_kw, input_kh, input_kd, c, batch_idx] += dy_idx * _alpha # + _beta * dx[x_idxs...]
312
329
elseif $ (name == :lpnorm )
313
330
grad = x[input_kw, input_kh, input_kd, c, batch_idx]^ (p- 1 ) * y_idx^ (1 - p)
314
331
dx[input_kw, input_kh, input_kd, c, batch_idx] += dy_idx * grad
0 commit comments