ONE - On-device Neural Engine
Loading...
Searching...
No Matches
OMUtils.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ONERT_MICRO_EXECUTE_UTILS_H
18#define ONERT_MICRO_EXECUTE_UTILS_H
19
20#include <cmath>
21#include "OMStatus.h"
23#include "core/OMRuntimeShape.h"
24#include "core/OMKernelData.h"
25
28#include "OMLog.h"
29
30namespace onert_micro
31{
32namespace execute
33{
34
35void readQuantParams(const circle::Tensor *tensor, long &zero_point, float &scale);
36template <typename T>
37OMStatus calculateActivationRange(circle::ActivationFunctionType activation, T *activation_min,
38 T *activation_max)
39{
40 switch (activation)
41 {
42 case circle::ActivationFunctionType::ActivationFunctionType_NONE:
43 *activation_min = std::numeric_limits<T>::lowest();
44 *activation_max = std::numeric_limits<T>::max();
45 break;
46 case circle::ActivationFunctionType::ActivationFunctionType_RELU:
47 *activation_min = 0;
48 *activation_max = std::numeric_limits<T>::max();
49 break;
50 case circle::ActivationFunctionType::ActivationFunctionType_RELU_N1_TO_1:
51 *activation_min = -1;
52 *activation_max = 1;
53 break;
54 case circle::ActivationFunctionType::ActivationFunctionType_RELU6:
55 *activation_min = 0;
56 *activation_max = 6;
57 break;
58 default:
59 assert(false && "Unsupported activation.");
61 }
62
63 return Ok;
64}
65
66inline double getQuantizedConvolutionMultipler(float input_scale, float filter_scale,
67 float output_scale)
68{
69 const double input_product_scale = static_cast<double>(input_scale * filter_scale);
70
71 assert(input_product_scale >= 0);
72
73 assert(output_scale != 0.f);
74
75 return input_product_scale / static_cast<double>(output_scale);
76}
77
78// Decompose a double multiplier into a Q0.31 int32 representation of its
79// significand, and shift representation of its exponent.
80//
81// Handles an arbitrary positive multiplier. The 'shift' output-value is
82// basically the 'floating-point exponent' of the multiplier:
83// Negative for a right-shift (when the multiplier is <1), positive for a
84// left-shift (when the multiplier is >1)
85void quantizeMultiplier(double double_multiplier, int32_t *quantized_multiplier, int *shift);
86
87// Decompose a double multiplier into a Q0.31 int32 representation of its
88// significand, and shift representation of NEGATIVE its exponent ---
89// this is intended as a RIGHT-shift.
90//
91// Restricted to the case where the multiplier < 1 (and non-negative).
92void quantizeMultiplierSmallerThanOneExp(double double_multiplier, int32_t *quantized_multiplier,
93 int *left_shift);
94
95inline std::vector<double>
97 float output_scale)
98{
99 std::vector<double> effective_output_scales;
100 size_t n = filter_scale->size();
101 effective_output_scales.reserve(n);
102 for (size_t i = 0; i < n; ++i)
103 {
104 effective_output_scales.push_back(
105 getQuantizedConvolutionMultipler(input_scale, filter_scale->operator[](i), output_scale));
106 }
107 return effective_output_scales;
108}
109
110OMStatus calculateActivationRangeQuantized(circle::ActivationFunctionType activation,
111 int32_t output_zero_point, float output_scale,
112 circle::TensorType data_type, int32_t *activation_min,
113 int32_t *activation_max);
114
115inline int computeOutSize(circle::Padding padding, int image_size, int filter_size, int stride,
116 int dilation_rate = 1)
117{
118 int effective_filter_size = (filter_size - 1) * dilation_rate + 1;
119
120 if (stride == 0)
121 return 0;
122
123 switch (padding)
124 {
125 case circle::Padding_SAME:
126 return (image_size + stride - 1) / stride;
127 case circle::Padding_VALID:
128 return (image_size + stride - effective_filter_size) / stride;
129 default:
130 return 0;
131 }
132}
133
134inline int computePadding(int32_t stride, int32_t dilation_rate, int32_t in_size,
135 int32_t filter_size, int32_t out_size)
136{
137 int32_t effective_filter_size = (filter_size - 1) * dilation_rate + 1;
138 int32_t padding = ((out_size - 1) * stride + effective_filter_size - in_size) / 2;
139 return padding > 0 ? padding : 0;
140}
141
142inline void computePaddingHeightWidth(int32_t stride_height, int32_t stride_width,
143 int32_t dilation_rate_height, int32_t dilation_rate_width,
144 int32_t in_height, int32_t in_width, int32_t filter_height,
145 int32_t filter_width, circle::Padding padding,
146 int32_t *padding_h, int32_t *padding_w)
147{
148
149 int out_width =
150 computeOutSize(padding, in_width, filter_width, stride_width, dilation_rate_width);
151 int out_height =
152 computeOutSize(padding, in_height, filter_height, stride_height, dilation_rate_height);
153
154 *padding_h =
155 computePadding(stride_height, dilation_rate_height, in_height, filter_height, out_height);
156
157 *padding_w = computePadding(stride_width, dilation_rate_width, in_width, filter_width, out_width);
158}
159
160void calculateQuantParams(core::ArithmeticQuantParams &params, const circle::Tensor *input1,
161 const circle::Tensor *input2, const circle::Tensor *output,
162 circle::ActivationFunctionType act);
163
164OMStatus SISOHeader(const OMExecuteArgs &execute_args, const circle::Tensor **input,
165 const circle::Tensor **output, uint8_t **input_data, uint8_t **output_data);
166
167OMStatus TISOHeader(const OMExecuteArgs &execute_args, const circle::Tensor **input1,
168 const circle::Tensor **input2, const circle::Tensor **output,
169 OMRuntimeKernel *runtime_kernel);
170
171inline int calculateInputRadius(int input_integer_bits, int input_left_shift, int total_signed_bits)
172{
173 const double max_input_rescaled = 1.0 * ((1 << input_integer_bits) - 1) *
174 (1LL << (total_signed_bits - input_integer_bits)) /
175 (1LL << input_left_shift);
176 // Tighten bound using floor. Suppose that we could use the exact value.
177 // After scaling the difference, the result would be at the maximum. Thus we
178 // must ensure that our value has lower magnitude.
179 return static_cast<int>(std::floor(max_input_rescaled));
180}
181
182} // namespace execute
183} // namespace onert_micro
184
185#endif // ONERT_MICRO_EXECUTE_UTILS_H
SizeT size() const
Definition vector.h:164
void quantizeMultiplier(double double_multiplier, int32_t *quantized_multiplier, int *shift)
Definition OMUtils.cpp:23
double getQuantizedConvolutionMultipler(float input_scale, float filter_scale, float output_scale)
Definition OMUtils.h:66
int computeOutSize(circle::Padding padding, int image_size, int filter_size, int stride, int dilation_rate=1)
Definition OMUtils.h:115
OMStatus SISOHeader(const OMExecuteArgs &execute_args, const circle::Tensor **input, const circle::Tensor **output, uint8_t **input_data, uint8_t **output_data)
Definition OMUtils.cpp:159
std::vector< double > getQuantizedConvolutionMultiplers(float input_scale, const flatbuffers::Vector< float > *filter_scale, float output_scale)
Definition OMUtils.h:96
void readQuantParams(const circle::Tensor *tensor, long &zero_point, float &scale)
Definition OMUtils.cpp:143
OMStatus calculateActivationRangeQuantized(circle::ActivationFunctionType activation, int32_t output_zero_point, float output_scale, circle::TensorType data_type, int32_t *activation_min, int32_t *activation_max)
Definition OMUtils.cpp:112
void calculateQuantParams(core::ArithmeticQuantParams &params, const circle::Tensor *input1, const circle::Tensor *input2, const circle::Tensor *output, circle::ActivationFunctionType act)
Definition OMUtils.cpp:194
void quantizeMultiplierSmallerThanOneExp(double double_multiplier, int32_t *quantized_multiplier, int *left_shift)
Definition OMUtils.cpp:60
OMStatus calculateActivationRange(circle::ActivationFunctionType activation, T *activation_min, T *activation_max)
Definition OMUtils.h:37
OMStatus TISOHeader(const OMExecuteArgs &execute_args, const circle::Tensor **input1, const circle::Tensor **input2, const circle::Tensor **output, OMRuntimeKernel *runtime_kernel)
Definition OMUtils.cpp:240
int calculateInputRadius(int input_integer_bits, int input_left_shift, int total_signed_bits)
Definition OMUtils.h:171
int computePadding(int32_t stride, int32_t dilation_rate, int32_t in_size, int32_t filter_size, int32_t out_size)
Definition OMUtils.h:134
void computePaddingHeightWidth(int32_t stride_height, int32_t stride_width, int32_t dilation_rate_height, int32_t dilation_rate_width, int32_t in_height, int32_t in_width, int32_t filter_height, int32_t filter_width, circle::Padding padding, int32_t *padding_h, int32_t *padding_w)
Definition OMUtils.h:142
@ UnsupportedActivation
Definition OMStatus.h:28