From 2ceb27c9373c2f6c4f5c4052a8a8571c2d737525 Mon Sep 17 00:00:00 2001 From: Balyshev Artem <43214667+BalyshevArtem@users.noreply.github.com> Date: Tue, 25 Jun 2024 11:35:46 +0300 Subject: [PATCH] [onert-micro] Reduce code duplication (#13278) This pr reduces code duplication for pooling execute part and for Mul and Add ops. ONE-DCO-1.0-Signed-off-by: Artem Balyshev --- .../onert-micro/include/execute/OMUtils.h | 1 + .../include/execute/kernels/PoolingCommon.h | 49 +++++++ .../onert-micro/src/execute/CMakeLists.txt | 1 + .../onert-micro/src/execute/OMUtils.cpp | 16 ++ .../onert-micro/src/execute/kernels/Add.cpp | 40 ++--- .../src/execute/kernels/AveragePool2D.cpp | 129 +++-------------- .../src/execute/kernels/L2Pool2D.cpp | 115 +++------------ .../src/execute/kernels/MaxPool2D.cpp | 129 +++-------------- .../onert-micro/src/execute/kernels/Mul.cpp | 39 ++--- .../src/execute/kernels/PoolingCommon.cpp | 137 ++++++++++++++++++ 10 files changed, 286 insertions(+), 370 deletions(-) create mode 100644 onert-micro/onert-micro/include/execute/kernels/PoolingCommon.h create mode 100644 onert-micro/onert-micro/src/execute/kernels/PoolingCommon.cpp diff --git a/onert-micro/onert-micro/include/execute/OMUtils.h b/onert-micro/onert-micro/include/execute/OMUtils.h index 413cf3e4e64..abb7a8006f1 100644 --- a/onert-micro/onert-micro/include/execute/OMUtils.h +++ b/onert-micro/onert-micro/include/execute/OMUtils.h @@ -27,6 +27,7 @@ namespace onert_micro namespace execute { +void readQuantParams(const circle::Tensor *tensor, long &zero_point, float &scale); template OMStatus calculateActivationRange(circle::ActivationFunctionType activation, T *activation_min, T *activation_max) diff --git a/onert-micro/onert-micro/include/execute/kernels/PoolingCommon.h b/onert-micro/onert-micro/include/execute/kernels/PoolingCommon.h new file mode 100644 index 00000000000..0e8da8e388a --- /dev/null +++ b/onert-micro/onert-micro/include/execute/kernels/PoolingCommon.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved + * + * 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 + * + * http://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. + */ + +#ifndef ONERT_MICRO_EXECUTE_KERNELS_POOLING_COMMON_H +#define ONERT_MICRO_EXECUTE_KERNELS_POOLING_COMMON_H + +#include "OMStatus.h" + +#include "core/OMUtils.h" +#include "core/OMKernelData.h" + +#include "execute/OMKernelExecutionBuilder.h" +#include "execute/OMUtils.h" +#include "execute/OMRuntimeKernel.h" +#include + +namespace onert_micro +{ +namespace execute +{ + +OMStatus execute_pooling_common( + const OMExecuteArgs &execute_args, + const std::function + &f_float, + const std::function + &f_int8); + +} // namespace execute +} // namespace onert_micro + +#endif // ONERT_MICRO_EXECUTE_KERNELS_POOLING_COMMON_H diff --git a/onert-micro/onert-micro/src/execute/CMakeLists.txt b/onert-micro/onert-micro/src/execute/CMakeLists.txt index 2e3fe849921..142e1cec337 100644 --- a/onert-micro/onert-micro/src/execute/CMakeLists.txt +++ b/onert-micro/onert-micro/src/execute/CMakeLists.txt @@ -15,6 +15,7 @@ set(SOURCES OMRuntimeKernel.cpp OMUtils.cpp kernels/ConvolutionCommon.cpp + kernels/PoolingCommon.cpp ) # Add configure kernels diff --git a/onert-micro/onert-micro/src/execute/OMUtils.cpp b/onert-micro/onert-micro/src/execute/OMUtils.cpp index 4903080e116..a207083b8c0 100644 --- a/onert-micro/onert-micro/src/execute/OMUtils.cpp +++ b/onert-micro/onert-micro/src/execute/OMUtils.cpp @@ -139,3 +139,19 @@ OMStatus onert_micro::execute::calculateActivationRangeQuantized( return calculateActivationRangeQuantizedImpl(activation, qmin, qmax, output_zero_point, output_scale, activation_min, activation_max); } + +void onert_micro::execute::readQuantParams(const circle::Tensor *tensor, long &zero_point, + float &scale) +{ + // additional check + assert(tensor->quantization() != nullptr); // Fix caller + assert(tensor->quantization()->scale() != nullptr and + tensor->quantization()->scale()->size() == 1); // Fix caller + assert(tensor->quantization()->zero_point() != nullptr and + tensor->quantization()->zero_point()->size() == 1); // Fix caller + + // read zero point + zero_point = tensor->quantization()->zero_point()->operator[](0); + // read scale + scale = tensor->quantization()->scale()->operator[](0); +} diff --git a/onert-micro/onert-micro/src/execute/kernels/Add.cpp b/onert-micro/onert-micro/src/execute/kernels/Add.cpp index cebe900f876..c08f9c4a445 100644 --- a/onert-micro/onert-micro/src/execute/kernels/Add.cpp +++ b/onert-micro/onert-micro/src/execute/kernels/Add.cpp @@ -37,32 +37,20 @@ void calculateQuantParams(core::ArithmeticQuantParams ¶ms, const circle::Ten const circle::Tensor *input2, const circle::Tensor *output, circle::ActivationFunctionType act) { - assert(input1->quantization() != nullptr); // Fix caller - assert(input2->quantization() != nullptr); // Fix caller - assert(output->quantization() != nullptr); // Fix caller - - assert(input1->quantization()->scale() != nullptr and - input1->quantization()->scale()->size() == 1); // Fix caller - assert(input2->quantization()->scale() != nullptr and - input2->quantization()->scale()->size() == 1); // Fix caller - assert(output->quantization()->scale() != nullptr and - output->quantization()->scale()->size() == 1); // Fix caller - - assert(input1->quantization()->zero_point() != nullptr and - input1->quantization()->zero_point()->size() == 1); // Fix caller - assert(input2->quantization()->zero_point() != nullptr and - input2->quantization()->zero_point()->size() == 1); // Fix caller - assert(output->quantization()->zero_point() != nullptr and - output->quantization()->zero_point()->size() == 1); // Fix caller - - // 8bit -> 8bit general quantized path, with general rescalings - const auto input1_zp = input1->quantization()->zero_point()->operator[](0); - const auto input2_zp = input2->quantization()->zero_point()->operator[](0); - const auto output_zp = output->quantization()->zero_point()->operator[](0); - - const auto input1_scale = input1->quantization()->scale()->operator[](0); - const auto input2_scale = input2->quantization()->scale()->operator[](0); - const auto output_scale = output->quantization()->scale()->operator[](0); + long input1_zp; + long input2_zp; + long output_zp; + + float input1_scale; + float input2_scale; + float output_scale; + + // Read input1 quant params + readQuantParams(input1, input1_zp, input1_scale); + // Read input2 quant params + readQuantParams(input2, input2_zp, input2_scale); + // Read output quant params + readQuantParams(output, output_zp, output_scale); params.input1_offset = -static_cast(input1_zp); params.input2_offset = -static_cast(input2_zp); diff --git a/onert-micro/onert-micro/src/execute/kernels/AveragePool2D.cpp b/onert-micro/onert-micro/src/execute/kernels/AveragePool2D.cpp index f33c4cc7aaa..671b0057e73 100644 --- a/onert-micro/onert-micro/src/execute/kernels/AveragePool2D.cpp +++ b/onert-micro/onert-micro/src/execute/kernels/AveragePool2D.cpp @@ -14,128 +14,33 @@ * limitations under the License. */ -#include "OMStatus.h" - -#include "core/OMUtils.h" -#include "core/OMKernelData.h" - -#include "execute/OMKernelExecutionBuilder.h" -#include "execute/OMUtils.h" -#include "execute/OMRuntimeKernel.h" - +#include "execute/kernels/PoolingCommon.h" #include "PALAveragePool2D.h" using namespace onert_micro; using namespace onert_micro::execute; -namespace -{ - -constexpr uint32_t inputTensorIdx = 0; -constexpr uint32_t outputTensorIdx = 0; - -} // namespace - // NOTE: doesnt currently support dynamic shapes OMStatus onert_micro::execute::execute_kernel_CircleAveragePool2D(const OMExecuteArgs &execute_args) { - core::OMRuntimeContext &runtime_context = execute_args.runtime_context; - core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage; - uint16_t op_index = execute_args.kernel_index; - - const circle::Tensor *input = nullptr; - const circle::Tensor *output = nullptr; - - uint8_t *input_data = nullptr; - uint8_t *output_data = nullptr; - - OMStatus status = Ok; - - const circle::Pool2DOptions *options = nullptr; - { - OMRuntimeKernel runtime_kernel; - runtime_kernel.readKernel(op_index, runtime_context); - - input = runtime_kernel.inputs[inputTensorIdx]; - output = runtime_kernel.outputs[outputTensorIdx]; + auto avg_pool_float_lambda = [](const core::Pool2DParams ¶ms, + const core::OMRuntimeShape &input_shape, const float *input_data, + const core::OMRuntimeShape &output_shape, float *output_data) { + return pal::AveragePool(params, input_shape, input_data, output_shape, output_data); + }; - assert(input != nullptr); - assert(output != nullptr); - - status = runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context); - if (status != Ok) - return status; - - input_data = runtime_kernel.inputs_data[inputTensorIdx]; - output_data = runtime_kernel.outputs_data[outputTensorIdx]; - - options = runtime_kernel.first_operator->builtin_options_as_Pool2DOptions(); - } - - assert(input_data != nullptr); - assert(output_data != nullptr); - assert(options != nullptr); - - core::OMRuntimeShape input_shape(input); - - int32_t padding_h = 0; - int32_t padding_w = 0; - - const int input_width = input_shape.dims(2); - const int input_height = input_shape.dims(1); - execute::computePaddingHeightWidth( - options->stride_h(), options->stride_w(), 1 /* dilation_rate_height */, - 1 /* dilation_rate_width */, input_height, input_width, options->filter_height(), - options->filter_width(), options->padding(), &padding_h, &padding_w); - - core::Pool2DParams params{}; - params.pad_h = padding_h; - params.pad_w = padding_w; - params.stride_h = options->stride_h(); - params.stride_w = options->stride_w(); - params.filter_h = options->filter_height(); - params.filter_w = options->filter_width(); - - switch (input->type()) - { -#ifndef DIS_FLOAT - case circle::TensorType_FLOAT32: - { - calculateActivationRange(options->fused_activation_function(), ¶ms.activation_min, - ¶ms.activation_max); - status = pal::AveragePool(params, input_shape, core::utils::castInputData(input_data), - core::OMRuntimeShape(output), - core::utils::castOutputData(output_data)); - } - break; -#endif // DIS_FLOAT #ifndef DIS_QUANT - case circle::TensorType_INT8: - { - assert(output->quantization() != nullptr); - assert(output->quantization()->scale() != nullptr); - assert(output->quantization()->scale()->size() == 1); - const auto output_scale = output->quantization()->scale()->operator[](0); - - assert(output->quantization()->zero_point() != nullptr); - assert(output->quantization()->zero_point()->size() == 1); - const auto output_zp = output->quantization()->zero_point()->operator[](0); - - calculateActivationRangeQuantized( - options->fused_activation_function(), output_zp, output_scale, output->type(), - ¶ms.quantized_activation_min, ¶ms.quantized_activation_max); - status = pal::AveragePool(params, input_shape, core::utils::castInputData(input_data), - core::OMRuntimeShape(output), - core::utils::castOutputData(output_data)); - } - break; + auto avg_pool_int8_lambda = [](const core::Pool2DParams ¶ms, + const core::OMRuntimeShape &input_shape, const int8_t *input_data, + const core::OMRuntimeShape &output_shape, int8_t *output_data) { + return pal::AveragePool(params, input_shape, input_data, output_shape, output_data); + }; +#else + auto avg_pool_int8_lambda = [](const core::Pool2DParams ¶ms, + const core::OMRuntimeShape &input_shape, const int8_t *input_data, + const core::OMRuntimeShape &output_shape, + int8_t *output_data) { return UnsupportedType; }; #endif // DIS_QUANT - default: - { - status = UnsupportedType; - assert(false && "Unsupported type."); - } - } - return status; + return execute_pooling_common(execute_args, avg_pool_float_lambda, avg_pool_int8_lambda); } diff --git a/onert-micro/onert-micro/src/execute/kernels/L2Pool2D.cpp b/onert-micro/onert-micro/src/execute/kernels/L2Pool2D.cpp index 4e9e08b378d..032652a2fb6 100644 --- a/onert-micro/onert-micro/src/execute/kernels/L2Pool2D.cpp +++ b/onert-micro/onert-micro/src/execute/kernels/L2Pool2D.cpp @@ -14,107 +14,32 @@ * limitations under the License. */ -#include "OMStatus.h" - -#include "core/OMUtils.h" -#include "core/OMKernelData.h" - -#include "execute/OMKernelExecutionBuilder.h" -#include "execute/OMUtils.h" -#include "execute/OMRuntimeKernel.h" - +#include "execute/kernels/PoolingCommon.h" #include "PALL2Pool2D.h" using namespace onert_micro; using namespace onert_micro::execute; -namespace -{ - -constexpr uint32_t inputTensorIdx = 0; -constexpr uint32_t outputTensorIdx = 0; - -} // namespace - // NOTE: doesnt currently support dynamic shapes OMStatus onert_micro::execute::execute_kernel_CircleL2Pool2D(const OMExecuteArgs &execute_args) { - core::OMRuntimeContext &runtime_context = execute_args.runtime_context; - core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage; - uint16_t op_index = execute_args.kernel_index; - - const circle::Tensor *input = nullptr; - const circle::Tensor *output = nullptr; - - uint8_t *input_data = nullptr; - uint8_t *output_data = nullptr; - - OMStatus status = Ok; - - const circle::Pool2DOptions *options = nullptr; - { - OMRuntimeKernel runtime_kernel; - runtime_kernel.readKernel(op_index, runtime_context); - - input = runtime_kernel.inputs[inputTensorIdx]; - output = runtime_kernel.outputs[outputTensorIdx]; - - assert(input != nullptr); - assert(output != nullptr); - - status = runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context); - if (status != Ok) - return status; - - input_data = runtime_kernel.inputs_data[inputTensorIdx]; - output_data = runtime_kernel.outputs_data[outputTensorIdx]; - - options = runtime_kernel.first_operator->builtin_options_as_Pool2DOptions(); - } - - assert(input_data != nullptr); - assert(output_data != nullptr); - assert(options != nullptr); - - core::OMRuntimeShape input_shape(input); - - int32_t padding_h = 0; - int32_t padding_w = 0; - - const int input_width = input_shape.dims(2); - const int input_height = input_shape.dims(1); - execute::computePaddingHeightWidth( - options->stride_h(), options->stride_w(), 1 /* dilation_rate_height */, - 1 /* dilation_rate_width */, input_height, input_width, options->filter_height(), - options->filter_width(), options->padding(), &padding_h, &padding_w); - - core::Pool2DParams params{}; - params.pad_h = padding_h; - params.pad_w = padding_w; - params.stride_h = options->stride_h(); - params.stride_w = options->stride_w(); - params.filter_h = options->filter_height(); - params.filter_w = options->filter_width(); - - switch (input->type()) - { -#ifndef DIS_FLOAT - case circle::TensorType_FLOAT32: - { - calculateActivationRange(options->fused_activation_function(), ¶ms.activation_min, - ¶ms.activation_max); - status = - pal::L2Pool(params, input_shape, core::utils::castInputData(input_data), - core::OMRuntimeShape(output), core::utils::castOutputData(output_data)); - } - break; -#endif // DIS_FLOAT - default: - { - status = UnsupportedType; - assert(false && "Unsupported type."); - } - } - - return status; + auto l2_pool_float_lambda = [](const core::Pool2DParams ¶ms, + const core::OMRuntimeShape &input_shape, const float *input_data, + const core::OMRuntimeShape &output_shape, float *output_data) { + return pal::L2Pool(params, input_shape, input_data, output_shape, output_data); + }; + +#ifndef DIS_QUANT + auto l2_pool_int8_lambda = [](const core::Pool2DParams ¶ms, + const core::OMRuntimeShape &input_shape, const int8_t *input_data, + const core::OMRuntimeShape &output_shape, + int8_t *output_data) { return UnsupportedType; }; +#else + auto l2_pool_int8_lambda = [](const core::Pool2DParams ¶ms, + const core::OMRuntimeShape &input_shape, const int8_t *input_data, + const core::OMRuntimeShape &output_shape, + int8_t *output_data) { return UnsupportedType; }; +#endif // DIS_QUANT + + return execute_pooling_common(execute_args, l2_pool_float_lambda, l2_pool_int8_lambda); } diff --git a/onert-micro/onert-micro/src/execute/kernels/MaxPool2D.cpp b/onert-micro/onert-micro/src/execute/kernels/MaxPool2D.cpp index 436312b72ed..b27e3fcb659 100644 --- a/onert-micro/onert-micro/src/execute/kernels/MaxPool2D.cpp +++ b/onert-micro/onert-micro/src/execute/kernels/MaxPool2D.cpp @@ -14,128 +14,33 @@ * limitations under the License. */ -#include "OMStatus.h" - -#include "core/OMUtils.h" -#include "core/OMKernelData.h" - -#include "execute/OMKernelExecutionBuilder.h" -#include "execute/OMUtils.h" -#include "execute/OMRuntimeKernel.h" - +#include "execute/kernels/PoolingCommon.h" #include "PALMaxPool2D.h" using namespace onert_micro; using namespace onert_micro::execute; -namespace -{ - -constexpr uint32_t inputTensorIdx = 0; -constexpr uint32_t outputTensorIdx = 0; - -} // namespace - // NOTE: doesnt currently support dynamic shapes OMStatus onert_micro::execute::execute_kernel_CircleMaxPool2D(const OMExecuteArgs &execute_args) { - core::OMRuntimeContext &runtime_context = execute_args.runtime_context; - core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage; - uint16_t op_index = execute_args.kernel_index; - - const circle::Tensor *input = nullptr; - const circle::Tensor *output = nullptr; - - uint8_t *input_data = nullptr; - uint8_t *output_data = nullptr; - - OMStatus status = Ok; - - const circle::Pool2DOptions *options = nullptr; - { - OMRuntimeKernel runtime_kernel; - runtime_kernel.readKernel(op_index, runtime_context); - - input = runtime_kernel.inputs[inputTensorIdx]; - output = runtime_kernel.outputs[outputTensorIdx]; + auto max_pool_float_lambda = [](const core::Pool2DParams ¶ms, + const core::OMRuntimeShape &input_shape, const float *input_data, + const core::OMRuntimeShape &output_shape, float *output_data) { + return pal::MaxPool(params, input_shape, input_data, output_shape, output_data); + }; - assert(input != nullptr); - assert(output != nullptr); - - status = runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context); - if (status != Ok) - return status; - - input_data = runtime_kernel.inputs_data[inputTensorIdx]; - output_data = runtime_kernel.outputs_data[outputTensorIdx]; - - options = runtime_kernel.first_operator->builtin_options_as_Pool2DOptions(); - } - - assert(input_data != nullptr); - assert(output_data != nullptr); - assert(options != nullptr); - - core::OMRuntimeShape input_shape(input); - - int32_t padding_h = 0; - int32_t padding_w = 0; - - const int input_width = input_shape.dims(2); - const int input_height = input_shape.dims(1); - execute::computePaddingHeightWidth( - options->stride_h(), options->stride_w(), 1 /* dilation_rate_height */, - 1 /* dilation_rate_width */, input_height, input_width, options->filter_height(), - options->filter_width(), options->padding(), &padding_h, &padding_w); - - core::Pool2DParams params{}; - params.pad_h = padding_h; - params.pad_w = padding_w; - params.stride_h = options->stride_h(); - params.stride_w = options->stride_w(); - params.filter_h = options->filter_height(); - params.filter_w = options->filter_width(); - - switch (input->type()) - { -#ifndef DIS_FLOAT - case circle::TensorType_FLOAT32: - { - calculateActivationRange(options->fused_activation_function(), ¶ms.activation_min, - ¶ms.activation_max); - status = - pal::MaxPool(params, input_shape, core::utils::castInputData(input_data), - core::OMRuntimeShape(output), core::utils::castOutputData(output_data)); - } - break; -#endif // DIS_FLOAT #ifndef DIS_QUANT - case circle::TensorType_INT8: - { - assert(output->quantization() != nullptr); - assert(output->quantization()->scale() != nullptr); - assert(output->quantization()->scale()->size() == 1); - const auto output_scale = output->quantization()->scale()->operator[](0); - - assert(output->quantization()->zero_point() != nullptr); - assert(output->quantization()->zero_point()->size() == 1); - const auto output_zp = output->quantization()->zero_point()->operator[](0); - - calculateActivationRangeQuantized( - options->fused_activation_function(), output_zp, output_scale, output->type(), - ¶ms.quantized_activation_min, ¶ms.quantized_activation_max); - status = pal::MaxPool(params, input_shape, core::utils::castInputData(input_data), - core::OMRuntimeShape(output), - core::utils::castOutputData(output_data)); - } - break; + auto max_pool_int8_lambda = [](const core::Pool2DParams ¶ms, + const core::OMRuntimeShape &input_shape, const int8_t *input_data, + const core::OMRuntimeShape &output_shape, int8_t *output_data) { + return pal::MaxPool(params, input_shape, input_data, output_shape, output_data); + }; +#else + auto max_pool_int8_lambda = [](const core::Pool2DParams ¶ms, + const core::OMRuntimeShape &input_shape, const int8_t *input_data, + const core::OMRuntimeShape &output_shape, + int8_t *output_data) { return UnsupportedType; }; #endif // DIS_QUANT - default: - { - status = UnsupportedType; - assert(false && "Unsupported type."); - } - } - return status; + return execute_pooling_common(execute_args, max_pool_float_lambda, max_pool_int8_lambda); } diff --git a/onert-micro/onert-micro/src/execute/kernels/Mul.cpp b/onert-micro/onert-micro/src/execute/kernels/Mul.cpp index 5e2c9d6e7a6..2f7fbec1d53 100644 --- a/onert-micro/onert-micro/src/execute/kernels/Mul.cpp +++ b/onert-micro/onert-micro/src/execute/kernels/Mul.cpp @@ -38,31 +38,20 @@ void calculateQuantParams(core::ArithmeticQuantParams ¶ms, const circle::Ten const circle::Tensor *input2, const circle::Tensor *output, circle::ActivationFunctionType act) { - assert(input1->quantization() != nullptr); // Fix caller - assert(input2->quantization() != nullptr); // Fix caller - assert(output->quantization() != nullptr); // Fix caller - - assert(input1->quantization()->scale() != nullptr and - input1->quantization()->scale()->size() == 1); // Fix caller - assert(input2->quantization()->scale() != nullptr and - input2->quantization()->scale()->size() == 1); // Fix caller - assert(output->quantization()->scale() != nullptr and - output->quantization()->scale()->size() == 1); // Fix caller - - assert(input1->quantization()->zero_point() != nullptr and - input1->quantization()->zero_point()->size() == 1); // Fix caller - assert(input2->quantization()->zero_point() != nullptr and - input2->quantization()->zero_point()->size() == 1); // Fix caller - assert(output->quantization()->zero_point() != nullptr and - output->quantization()->zero_point()->size() == 1); // Fix caller - - const auto input1_zp = input1->quantization()->zero_point()->operator[](0); - const auto input2_zp = input2->quantization()->zero_point()->operator[](0); - const auto output_zp = output->quantization()->zero_point()->operator[](0); - - const auto input1_scale = input1->quantization()->scale()->operator[](0); - const auto input2_scale = input2->quantization()->scale()->operator[](0); - const auto output_scale = output->quantization()->scale()->operator[](0); + long input1_zp; + long input2_zp; + long output_zp; + + float input1_scale; + float input2_scale; + float output_scale; + + // Read input1 quant params + readQuantParams(input1, input1_zp, input1_scale); + // Read input2 quant params + readQuantParams(input2, input2_zp, input2_scale); + // Read output quant params + readQuantParams(output, output_zp, output_scale); params.input1_offset = static_cast(input1_zp); params.input2_offset = static_cast(input2_zp); diff --git a/onert-micro/onert-micro/src/execute/kernels/PoolingCommon.cpp b/onert-micro/onert-micro/src/execute/kernels/PoolingCommon.cpp new file mode 100644 index 00000000000..be762b9b9f1 --- /dev/null +++ b/onert-micro/onert-micro/src/execute/kernels/PoolingCommon.cpp @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved + * + * 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 + * + * http://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. + */ + +#include "execute/kernels/PoolingCommon.h" +#include "execute/OMUtils.h" + +using namespace onert_micro; +using namespace onert_micro::core; + +namespace +{ + +constexpr uint32_t inputTensorIdx = 0; +constexpr uint32_t outputTensorIdx = 0; + +} // namespace + +OMStatus onert_micro::execute::execute_pooling_common( + const OMExecuteArgs &execute_args, + const std::function &f_float, + const std::function &f_int8) +{ + core::OMRuntimeContext &runtime_context = execute_args.runtime_context; + core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage; + uint16_t op_index = execute_args.kernel_index; + + const circle::Tensor *input = nullptr; + const circle::Tensor *output = nullptr; + + uint8_t *input_data = nullptr; + uint8_t *output_data = nullptr; + + OMStatus status = Ok; + + const circle::Pool2DOptions *options = nullptr; + { + OMRuntimeKernel runtime_kernel; + runtime_kernel.readKernel(op_index, runtime_context); + + input = runtime_kernel.inputs[inputTensorIdx]; + output = runtime_kernel.outputs[outputTensorIdx]; + + assert(input != nullptr); + assert(output != nullptr); + + status = runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context); + if (status != Ok) + return status; + + input_data = runtime_kernel.inputs_data[inputTensorIdx]; + output_data = runtime_kernel.outputs_data[outputTensorIdx]; + + options = runtime_kernel.first_operator->builtin_options_as_Pool2DOptions(); + } + + assert(input_data != nullptr); + assert(output_data != nullptr); + assert(options != nullptr); + + core::OMRuntimeShape input_shape(input); + + int32_t padding_h = 0; + int32_t padding_w = 0; + + const int input_width = input_shape.dims(2); + const int input_height = input_shape.dims(1); + execute::computePaddingHeightWidth( + options->stride_h(), options->stride_w(), 1 /* dilation_rate_height */, + 1 /* dilation_rate_width */, input_height, input_width, options->filter_height(), + options->filter_width(), options->padding(), &padding_h, &padding_w); + + core::Pool2DParams params{}; + params.pad_h = padding_h; + params.pad_w = padding_w; + params.stride_h = options->stride_h(); + params.stride_w = options->stride_w(); + params.filter_h = options->filter_height(); + params.filter_w = options->filter_width(); + + switch (input->type()) + { +#ifndef DIS_FLOAT + case circle::TensorType_FLOAT32: + { + calculateActivationRange(options->fused_activation_function(), ¶ms.activation_min, + ¶ms.activation_max); + status = + f_float(params, input_shape, core::utils::castInputData(input_data), + core::OMRuntimeShape(output), core::utils::castOutputData(output_data)); + } + break; +#endif // DIS_FLOAT +#ifndef DIS_QUANT + case circle::TensorType_INT8: + { + assert(output->quantization() != nullptr); + assert(output->quantization()->scale() != nullptr); + assert(output->quantization()->scale()->size() == 1); + const auto output_scale = output->quantization()->scale()->operator[](0); + + assert(output->quantization()->zero_point() != nullptr); + assert(output->quantization()->zero_point()->size() == 1); + const auto output_zp = output->quantization()->zero_point()->operator[](0); + + calculateActivationRangeQuantized( + options->fused_activation_function(), output_zp, output_scale, output->type(), + ¶ms.quantized_activation_min, ¶ms.quantized_activation_max); + status = + f_int8(params, input_shape, core::utils::castInputData(input_data), + core::OMRuntimeShape(output), core::utils::castOutputData(output_data)); + } + break; +#endif // DIS_QUANT + default: + { + status = UnsupportedType; + assert(false && "Unsupported type."); + } + } + + return status; +}