Преглед изворни кода

CMSIS-NN : s8 max pool basic function

Pure C max pool function for s8.
Felix Johnny пре 6 година
родитељ
комит
f16c44aae6

+ 41 - 0
CMSIS/NN/Include/arm_nnfunctions.h

@@ -1499,6 +1499,47 @@ extern    "C"
                              int8_t *input,
                              int16_t *tmp_buffer,
                              int8_t *output);
+
+  /**
+   * @brief s8 pure C max pooling function
+   * @param[in]       input_y     input tensor dimension along y
+   * @param[in]       input_x     input tensor dimension along x
+   * @param[in]       output_y    output tensor dimension along y
+   * @param[in]       output_x    output tensor dimension along x
+   * @param[in]       stride_y    stride along y
+   * @param[in]       stride_x    stride along x
+   * @param[in]       kernel_y    filter kernel size along y
+   * @param[in]       kernel_x    filter kernel size along x
+   * @param[in]       pad_y       padding size along y
+   * @param[in]       pad_x       padding size along x
+   * @param[in]       act_min     Activation min. Lower limit to clamp output to. Range: int8
+   * @param[in]       act_max     Activation max. Upper limit to clamp output to. Range: int8
+   * @param[in]       channel_in  number of input channels
+   * @param[in]       input       pointer to input tensor
+   * @param[in]       tmp_buffer  Not used.
+   * @param[in,out]   output      pointer to output tensor
+   *
+   * @details
+   *    - This basic implementation is recommended when number of channels is less than 4 and/or
+   *      dimensions are small.
+   *
+   */
+    void arm_max_pool_s8(const uint16_t input_y,
+                         const uint16_t input_x,
+                         const uint16_t output_y,
+                         const uint16_t output_x,
+                         const uint16_t stride_y,
+                         const uint16_t stride_x,
+                         const uint16_t kernel_y,
+                         const uint16_t kernel_x,
+                         const uint16_t pad_y,
+                         const uint16_t pad_x,
+                         const int8_t act_min,
+                         const int8_t act_max,
+                         const uint16_t channel_in,
+                         int8_t *input,
+                         int16_t *tmp_buffer,
+                         int8_t *output);
 /**
  * @defgroup Softmax Softmax Functions
  *

+ 3 - 0
CMSIS/NN/Include/arm_nnsupportfunctions.h

@@ -42,6 +42,9 @@ extern    "C"
 #define RIGHT_SHIFT(_shift) (_shift > 0 ? 0 : -_shift)
 #define Q31_MIN ((q31_t)(0x80000000L))
 #define Q31_MAX ((q31_t)(0x7FFFFFFFL))
+#define Q7_MIN ((q7_t)(0x80))
+#define Q7_MAX ((q7_t)(0x7F))
+
 
 #define MAX(A,B) ((A) > (B) ? (A) : (B))
 #define MIN(A,B) ((A) < (B) ? (A) : (B))

+ 105 - 0
CMSIS/NN/Source/PoolingFunctions/arm_max_pool_s8.c

@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2010-2019 Arm Limited or its affiliates. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* ----------------------------------------------------------------------
+ * Project:      CMSIS NN Library
+ * Title:        arm_max_pool_s8.c
+ * Description:  Pure C max pool implementation
+ *
+ * $Date:        August 2019
+ * $Revision:    V.1.0.0
+ *
+ * Target Processor:  Cortex-M cores
+ *
+ * -------------------------------------------------------------------- */
+
+#include "arm_nnfunctions.h"
+#include <arm_math.h>
+
+/**
+ *  @ingroup groupNN
+ */
+
+/**
+ * @addtogroup Pooling
+ * @{
+ */
+
+void arm_max_pool_s8(const uint16_t input_y,
+                     const uint16_t input_x,
+                     const uint16_t output_y,
+                     const uint16_t output_x,
+                     const uint16_t stride_y,
+                     const uint16_t stride_x,
+                     const uint16_t kernel_y,
+                     const uint16_t kernel_x,
+                     const uint16_t pad_y,
+                     const uint16_t pad_x,
+                     const int8_t act_min,
+                     const int8_t act_max,
+                     const uint16_t channel_in,
+                     int8_t *input,
+                     int16_t *tmp_buffer,
+                     int8_t *output)
+{
+    int32_t i_ch_in, i_out_x, i_out_y;
+    int32_t i_ker_x, i_ker_y;
+    (void)tmp_buffer;
+
+    for (i_out_y = 0; i_out_y < output_y; i_out_y++)
+    {
+        for (i_out_x = 0; i_out_x < output_x; i_out_x++)
+        {
+            for (i_ch_in = 0; i_ch_in < channel_in; i_ch_in++)
+            {
+                /* Native data type for inner loop variables  */
+                int32_t max_val = (int32_t)Q7_MIN;
+                /* Condition for kernel start dimension: (base_idx_<x,y> + ker_<x,y>_start) >= 0 */
+                const int32_t base_idx_y = (i_out_y * stride_y) - pad_y;
+                const int32_t base_idx_x = (i_out_x * stride_x) - pad_x;
+                const int32_t ker_y_start = MAX(0, -base_idx_y);
+                const int32_t ker_x_start = MAX(0, -base_idx_x);
+
+                /* Condition for kernel end dimension: (base_idx_<x,y> + ker_<x,y>_end) < input_<x,y> */
+                const int32_t ker_y_end = MIN(kernel_y, input_y - base_idx_y);
+                const int32_t ker_x_end = MIN(kernel_x, input_x - base_idx_x);
+
+                for (i_ker_y = ker_y_start; i_ker_y < ker_y_end; i_ker_y++)
+                {
+                    for (i_ker_x = ker_x_start; i_ker_x < ker_x_end; i_ker_x++)
+                    {
+                        const int32_t col_idx = base_idx_x + i_ker_x;
+                        const int32_t row_idx = base_idx_y + i_ker_y;
+
+                        max_val = MAX(input[(row_idx * input_x + col_idx) * channel_in + i_ch_in], max_val);
+                    }
+                }
+
+                /* Activation function */
+                max_val = MAX(max_val, act_min);
+                max_val = MIN(max_val, act_max);
+
+                output[i_ch_in + channel_in * (i_out_x + i_out_y * output_x)] = (int8_t)max_val;
+            }
+        }
+    }
+}
+
+/**
+ * @} end of Pooling group
+ */