aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Kunze <eric.kunze@arm.com>2021-09-21 16:56:20 -0700
committerEric Kunze <eric.kunze@arm.com>2021-09-24 16:19:50 -0700
commitb37e7fb865744536b708c8baa49b6415eab07b04 (patch)
tree179ca5c9322f342993c82a67a16208c810d4ba10
parentf1b531ac7a0a045301d39ba14d5c1dc5dc691ddc (diff)
downloadspecification-b37e7fb865744536b708c8baa49b6415eab07b04.tar.gz
Don't allow pooling ops with excessive padding
Padding larger than the kernel size leads to the odd effect where no values from the input tensor are used. This leads to a divide by 0 in AVG_POOL2D, as it only divides by the number of valid input values used, not padding. Change MAX_POOL2D to have the same limitation for consistency. Signed-off-by: Eric Kunze <eric.kunze@arm.com> Change-Id: I9cd0c0619f88f570d30c83053280460ae3d1cbfb
-rw-r--r--chapters/tensor_ops.adoc15
1 files changed, 13 insertions, 2 deletions
diff --git a/chapters/tensor_ops.adoc b/chapters/tensor_ops.adoc
index 9c10450..ff5f25a 100644
--- a/chapters/tensor_ops.adoc
+++ b/chapters/tensor_ops.adoc
@@ -70,8 +70,9 @@ for_each(left_index in left_shape) {
==== AVG_POOL2D
-This performs an average pooling over the given input tensor. A sliding window of size given by <kernel size> is passed over the input tensor, with the mean value being placed in the output tensor.
-
+This performs an average pooling over the given input tensor.
+A sliding window of size given by <kernel size> is passed over the input tensor, with the mean value being placed in the output tensor.
+When calculating the average, only the number of valid input tensor values, but not padding, are used to calculate the divisor.
*Arguments:*
|===
@@ -102,6 +103,11 @@ ERROR_IF(in_t != int8_t && output_zp != 0); // Zero point only for int8_t
ERROR_IF(kernel_y < 1 || kernel_x < 1); // kernel size must be >= 1
ERROR_IF(stride_y < 1 || stride_x < 1);
ERROR_IF(pad_top < 0 || pad_buttom < 0 || pad_left < 0 || pad_right < 0);
+// Padding must be less than kernel size to avoid
+// a divide-by-zero.
+ERROR_IF(pad_right >= kernel_x || pad_left >= kernel_x);
+ERROR_IF(pad_top >= kernel_y || pad_bottom >= kernel_y);
+
pad = flatten([0,0], pad, [0,0]);
for_each(0 <= n < N, 0 <= oy < H, 0 <= ox < W, 0 <= c < C ) {
in_t output_val;
@@ -462,6 +468,11 @@ None
ERROR_IF(kernel_y < 1 || kernel_x < 1); // kernel size must be >= 1
ERROR_IF(stride_y < 1 || stride_x < 1);
ERROR_IF(pad_top < 0 || pad_buttom < 0 || pad_left < 0 || pad_right < 0);
+// Padding must be less than kernel size, otherwise no
+// input values will be used.
+ERROR_IF(pad_right >= kernel_x || pad_left >= kernel_x);
+ERROR_IF(pad_top >= kernel_y || pad_bottom >= kernel_y);
+
for_each(0 <= n < N, 0 <= oy < H, 0 <= ox < W, 0 <= c < C ) {
in_t acc = minimum_value<in_t>;
iy = oy * stride_y - pad_top;