From 7c2cdbcf6385729784b0ff26e96bd58604b80ab9 Mon Sep 17 00:00:00 2001 From: Matthew Haddon Date: Thu, 7 Oct 2021 17:43:43 +0100 Subject: Force output shape to be correct for pooling operations The avg_pool2d and max_pool2d operators trigger an error_if statement if the output shape provided does not match the output shape generated by the operation given the input arguments. * Add pseudocode for floor operation * Fixed type in RESCALE op Signed-off-by: Matthew Haddon Change-Id: I087faa331c30becc05719cd1261f436019dcdeb5 --- chapters/pseudocode.adoc | 11 +++++++---- chapters/tensor_ops.adoc | 10 ++++++++-- chapters/type_conversion.adoc | 6 +++--- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/chapters/pseudocode.adoc b/chapters/pseudocode.adoc index e6b7604..5e6af5b 100644 --- a/chapters/pseudocode.adoc +++ b/chapters/pseudocode.adoc @@ -128,7 +128,7 @@ out_t truncate(in_t input) output is the sizeof(out_t) least significant bits in input. ---- -The following definition is used to flatten a list of lists into a single list +The following definition is used to flatten a list of lists into a single list. [source,c++] ---- @@ -142,10 +142,13 @@ in_t* flatten(in_t lists[]) { } ---- -The following helper function returns the length of a list +Generic helper functions used to keep the pseudocode concise. [source,c++] ---- int length(in_t input) - return number of elements in input ----- + return number of elements in input list + +int floor(in_t input) + return input value rounded down to nearest integer +---- \ No newline at end of file diff --git a/chapters/tensor_ops.adoc b/chapters/tensor_ops.adoc index 0b78c8f..ad4d75d 100644 --- a/chapters/tensor_ops.adoc +++ b/chapters/tensor_ops.adoc @@ -96,8 +96,11 @@ ERROR_IF(pad_top < 0 || pad_bottom < 0 || pad_left < 0 || pad_right < 0); // a divide-by-zero. ERROR_IF(pad_right >= kernel_x || pad_left >= kernel_x); ERROR_IF(pad_top >= kernel_y || pad_bottom >= kernel_y); +// Output shape must match expected shape given the input shape +// and arguments provided +ERROR_IF(H != floor((IH + pad_top + pad_bottom + stride_y - kernel_y) / stride_y)) +ERROR_IF(W != floor((IW + pad_left + pad_right + stride_x - kernel_x) / stride_x)) -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; acc_t acc = 0; @@ -428,6 +431,10 @@ ERROR_IF(pad_top < 0 || pad_bottom < 0 || pad_left < 0 || pad_right < 0); // 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); +// Output shape must match expected shape given the input shape +// and arguments provided +ERROR_IF(H != floor((IH + pad_top + pad_bottom + stride_y - kernel_y) / stride_y)) +ERROR_IF(W != floor((IW + pad_left + pad_right + stride_x - kernel_x) / stride_x)) for_each(0 <= n < N, 0 <= oy < H, 0 <= ox < W, 0 <= c < C ) { in_t acc = minimum_value; @@ -436,7 +443,6 @@ for_each(0 <= n < N, 0 <= oy < H, 0 <= ox < W, 0 <= c < C ) { for_each( 0 <= ky < kernel_y, 0 <= kx < kernel_x ) { y = iy + ky; x = ix + kx; - ERROR_IF(y >= IH + pad_bottom || x >= IW + pad_right); if (y >= 0 && y < IH && x >= 0 && x < IW) { in_t value = tensor_read(input, [N,IH,IW,C], [n,y,x,c]); acc = apply_max(acc, value); diff --git a/chapters/type_conversion.adoc b/chapters/type_conversion.adoc index 8619fc3..aa2218f 100644 --- a/chapters/type_conversion.adoc +++ b/chapters/type_conversion.adoc @@ -124,9 +124,9 @@ for_each(index in shape) { |Any|signed 32 to signed 8|int32_t|int8_t |Any|signed 32 to signed 16|int32_t|int16_t |Any|signed 32 to signed 32|int32_t|int32_t -|Any|signed 48 to signed 8|int48_t_t|int8_t -|Any|signed 48 to signed 16|int48_t_t|int16_t -|Any|signed 48 to signed 32|int48_t_t|int32_t +|Any|signed 48 to signed 8|int48_t|int8_t +|Any|signed 48 to signed 16|int48_t|int16_t +|Any|signed 48 to signed 32|int48_t|int32_t |Any|unsigned 8 to signed 8|uint8_t|int8_t |Any|signed 8 to unsigned 8|int8_t|uint8_t |=== -- cgit v1.2.1