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
29namespace onert_micro
30{
31namespace execute
32{
33
34void readQuantParams(const circle::Tensor *tensor, long &zero_point, float &scale);
35template <typename T>
36OMStatus calculateActivationRange(circle::ActivationFunctionType activation, T *activation_min,
37 T *activation_max)
38{
39 switch (activation)
40 {
41 case circle::ActivationFunctionType::ActivationFunctionType_NONE:
42 *activation_min = std::numeric_limits<T>::lowest();
43 *activation_max = std::numeric_limits<T>::max();
44 break;
45 case circle::ActivationFunctionType::ActivationFunctionType_RELU:
46 *activation_min = 0;
47 *activation_max = std::numeric_limits<T>::max();
48 break;
49 case circle::ActivationFunctionType::ActivationFunctionType_RELU_N1_TO_1:
50 *activation_min = -1;
51 *activation_max = 1;
52 break;
53 case circle::ActivationFunctionType::ActivationFunctionType_RELU6:
54 *activation_min = 0;
55 *activation_max = 6;
56 break;
57 default:
58 assert(false && "Unsupported activation.");
60 }
61
62 return Ok;
63}
64
65inline double getQuantizedConvolutionMultipler(float input_scale, float filter_scale,
66 float output_scale)
67{
68 const double input_product_scale = static_cast<double>(input_scale * filter_scale);
69
70 assert(input_product_scale >= 0);
71
72 assert(output_scale != 0.f);
73
74 return input_product_scale / static_cast<double>(output_scale);
75}
76
77// Decompose a double multiplier into a Q0.31 int32 representation of its
78// significand, and shift representation of its exponent.
79//
80// Handles an arbitrary positive multiplier. The 'shift' output-value is
81// basically the 'floating-point exponent' of the multiplier:
82// Negative for a right-shift (when the multiplier is <1), positive for a
83// left-shift (when the multiplier is >1)
84void quantizeMultiplier(double double_multiplier, int32_t *quantized_multiplier, int *shift);
85
86// Decompose a double multiplier into a Q0.31 int32 representation of its
87// significand, and shift representation of NEGATIVE its exponent ---
88// this is intended as a RIGHT-shift.
89//
90// Restricted to the case where the multiplier < 1 (and non-negative).
91void quantizeMultiplierSmallerThanOneExp(double double_multiplier, int32_t *quantized_multiplier,
92 int *left_shift);
93
94inline std::vector<double>
96 float output_scale)
97{
98 std::vector<double> effective_output_scales;
99 size_t n = filter_scale->size();
100 effective_output_scales.reserve(n);
101 for (size_t i = 0; i < n; ++i)
102 {
103 effective_output_scales.push_back(
104 getQuantizedConvolutionMultipler(input_scale, filter_scale->operator[](i), output_scale));
105 }
106 return effective_output_scales;
107}
108
109OMStatus calculateActivationRangeQuantized(circle::ActivationFunctionType activation,
110 int32_t output_zero_point, float output_scale,
111 circle::TensorType data_type, int32_t *activation_min,
112 int32_t *activation_max);
113
114inline int computeOutSize(circle::Padding padding, int image_size, int filter_size, int stride,
115 int dilation_rate = 1)
116{
117 int effective_filter_size = (filter_size - 1) * dilation_rate + 1;
118
119 if (stride == 0)
120 return 0;
121
122 switch (padding)
123 {
124 case circle::Padding_SAME:
125 return (image_size + stride - 1) / stride;
126 case circle::Padding_VALID:
127 return (image_size + stride - effective_filter_size) / stride;
128 default:
129 return 0;
130 }
131}
132
133inline int computePadding(int32_t stride, int32_t dilation_rate, int32_t in_size,
134 int32_t filter_size, int32_t out_size)
135{
136 int32_t effective_filter_size = (filter_size - 1) * dilation_rate + 1;
137 int32_t padding = ((out_size - 1) * stride + effective_filter_size - in_size) / 2;
138 return padding > 0 ? padding : 0;
139}
140
141inline void computePaddingHeightWidth(int32_t stride_height, int32_t stride_width,
142 int32_t dilation_rate_height, int32_t dilation_rate_width,
143 int32_t in_height, int32_t in_width, int32_t filter_height,
144 int32_t filter_width, circle::Padding padding,
145 int32_t *padding_h, int32_t *padding_w)
146{
147
148 int out_width =
149 computeOutSize(padding, in_width, filter_width, stride_width, dilation_rate_width);
150 int out_height =
151 computeOutSize(padding, in_height, filter_height, stride_height, dilation_rate_height);
152
153 *padding_h =
154 computePadding(stride_height, dilation_rate_height, in_height, filter_height, out_height);
155
156 *padding_w = computePadding(stride_width, dilation_rate_width, in_width, filter_width, out_width);
157}
158
159void calculateQuantParams(core::ArithmeticQuantParams &params, const circle::Tensor *input1,
160 const circle::Tensor *input2, const circle::Tensor *output,
161 circle::ActivationFunctionType act);
162
163OMStatus SISOHeader(const OMExecuteArgs &execute_args, const circle::Tensor **input,
164 const circle::Tensor **output, uint8_t **input_data, uint8_t **output_data);
165
166OMStatus TISOHeader(const OMExecuteArgs &execute_args, const circle::Tensor **input1,
167 const circle::Tensor **input2, const circle::Tensor **output,
168 OMRuntimeKernel *runtime_kernel);
169
170inline int calculateInputRadius(int input_integer_bits, int input_left_shift, int total_signed_bits)
171{
172 const double max_input_rescaled = 1.0 * ((1 << input_integer_bits) - 1) *
173 (1LL << (total_signed_bits - input_integer_bits)) /
174 (1LL << input_left_shift);
175 // Tighten bound using floor. Suppose that we could use the exact value.
176 // After scaling the difference, the result would be at the maximum. Thus we
177 // must ensure that our value has lower magnitude.
178 return static_cast<int>(std::floor(max_input_rescaled));
179}
180
181} // namespace execute
182} // namespace onert_micro
183
184#endif // ONERT_MICRO_EXECUTE_UTILS_H
uoffset_t size() const
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:65
int computeOutSize(circle::Padding padding, int image_size, int filter_size, int stride, int dilation_rate=1)
Definition OMUtils.h:114
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:95
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:36
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:170
int computePadding(int32_t stride, int32_t dilation_rate, int32_t in_size, int32_t filter_size, int32_t out_size)
Definition OMUtils.h:133
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:141
@ UnsupportedActivation
Definition OMStatus.h:28