ONE - On-device Neural Engine
Loading...
Searching...
No Matches
SVDF.cpp
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#include "OMStatus.h"
18
19#include "core/OMUtils.h"
20#include "core/OMDataType.h"
21#include "core/OMKernelData.h"
23
25#include "execute/OMUtils.h"
27
28#include "PALSVDF.h"
29
30using namespace onert_micro;
31using namespace onert_micro::core;
32using namespace onert_micro::execute;
33
34namespace
35{
36
37constexpr int inputTensorIdx = 0;
38constexpr int weightsFeatureTensorIdx = 1;
39constexpr int weightsTimeTensorIdx = 2;
40constexpr int biasTensorIdx = 3;
41constexpr int inputActivationStateTensorIdx =
42 4; // This is a variable tensor, and will be modified by this op.
43constexpr int outputTensorIdx = 0;
44
45void prepareQuantParams(core::SVDFQuantParams &params, const circle::Tensor *input,
46 const circle::Tensor *weights_feature, const circle::Tensor *weights_time,
47 const circle::Tensor *activation_state, const circle::Tensor *output)
48{
49 assert(input->quantization() != nullptr);
50 assert(output->quantization() != nullptr);
51 assert(weights_feature->quantization() != nullptr);
52 assert(weights_time->quantization() != nullptr);
53 assert(activation_state->quantization() != nullptr);
54
55 // Write zero points
56 params.input_zero_point =
57 static_cast<int32_t>(input->quantization()->zero_point()->operator[](0));
58 params.output_zero_point =
59 static_cast<int32_t>(output->quantization()->zero_point()->operator[](0));
61 static_cast<int32_t>(activation_state->quantization()->zero_point()->operator[](0));
62
63 // Calculate effective scales
64 const float effective_scale_1 = (input->quantization()->scale()->operator[](0) *
65 weights_feature->quantization()->scale()->operator[](0)) /
66 (activation_state->quantization()->scale()->operator[](0));
67 const float effective_scale_2 = (activation_state->quantization()->scale()->operator[](0) *
68 weights_time->quantization()->scale()->operator[](0)) /
69 (output->quantization()->scale()->operator[](0));
70
71 execute::quantizeMultiplier(effective_scale_1, &params.effective_scale_1_a,
72 &params.effective_scale_1_b);
73 execute::quantizeMultiplier(effective_scale_2, &params.effective_scale_2_a,
74 &params.effective_scale_2_b);
75}
76
77} // namespace
78
79namespace onert_micro
80{
81namespace execute
82{
83
85{
86 core::OMRuntimeContext &runtime_context = execute_args.runtime_context;
87 core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage;
88 uint16_t op_index = execute_args.kernel_index;
89
90 const circle::Tensor *input;
91 const circle::Tensor *weights_feature;
92 const circle::Tensor *weights_time;
93 const circle::Tensor *bias;
94 const circle::Tensor *activation_state;
95
96 const circle::Tensor *output;
97
98 uint8_t *input_data;
99 uint8_t *weights_feature_data;
100 uint8_t *weights_time_data;
101 uint8_t *bias_data;
102 uint8_t *activation_state_data;
103 uint8_t *output_data;
104 const circle::SVDFOptions *options = nullptr;
105 // Read kernel
106 {
107 execute::OMRuntimeKernel runtime_kernel;
108 OMStatus status = runtime_kernel.readKernel(op_index, runtime_context);
109 if (status != Ok)
110 return status;
111
112 input = runtime_kernel.inputs[inputTensorIdx];
113 weights_feature = runtime_kernel.inputs[weightsFeatureTensorIdx];
114 weights_time = runtime_kernel.inputs[weightsTimeTensorIdx];
115 bias = runtime_kernel.inputs[biasTensorIdx];
116 activation_state = runtime_kernel.inputs[inputActivationStateTensorIdx];
117
118 output = runtime_kernel.outputs[outputTensorIdx];
119
120 assert(input != nullptr);
121 assert(weights_feature != nullptr);
122 assert(weights_time != nullptr);
123 // bias can be nullptr
124 assert(activation_state != nullptr);
125 assert(output != nullptr);
126
127 status = runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context);
128 if (status != Ok)
129 return status;
130
131 input_data = runtime_kernel.inputs_data[inputTensorIdx];
132 weights_feature_data = runtime_kernel.inputs_data[weightsFeatureTensorIdx];
133 weights_time_data = runtime_kernel.inputs_data[weightsTimeTensorIdx];
134 bias_data = runtime_kernel.inputs_data[biasTensorIdx];
135 activation_state_data = runtime_kernel.inputs_data[inputActivationStateTensorIdx];
136 output_data = runtime_kernel.outputs_data[outputTensorIdx];
137
138 assert(input_data != nullptr);
139 assert(weights_feature_data != nullptr);
140 assert(weights_time_data != nullptr);
141 // bias can be nullptr
142 assert(output_data != nullptr);
143
144 options = runtime_kernel.first_operator->builtin_options_as_SVDFOptions();
145 }
146
147 OMStatus status;
148 OMRuntimeShape input_shape(input);
149 OMRuntimeShape weights_feature_shape(weights_feature);
150 OMRuntimeShape weights_time_shape(weights_time);
151 OMRuntimeShape activation_state_shape(activation_state);
153
154 // Define input constants based on input tensor definition above:
155 const int rank = options->rank();
156 const int input_size = input_shape.dims(1);
157 const int batch_size = input_shape.dims(0);
158 const int num_filters = weights_feature_shape.dims(0);
159
160 const int num_units = num_filters / rank;
161 const int memory_size = weights_time_shape.dims(1);
162
163 const auto activation_state_size =
164 activation_state_shape.flatSize() * sizeof(core::OMDataType(output->type()));
165 status =
166 core::memory::OMMemoryManager::allocateMemory(activation_state_size, &activation_state_data);
167 if (status != Ok)
168 return status;
169
170 std::memset(activation_state_data, 0, activation_state_size);
171
172 switch (input->type())
173 {
174#ifndef DIS_FLOAT
175 case circle::TensorType_FLOAT32:
176 {
177 // Temporary buffer
178 uint8_t *scratch_buffer;
180 batch_size * num_filters * sizeof(core::OMDataType(output->type())), &scratch_buffer);
181
182 assert(status == Ok);
183 if (status != Ok)
184 return status;
185 status = pal::SVDF(
186 utils::castInputData<float>(input_data), utils::castInputData<float>(weights_feature_data),
187 utils::castInputData<float>(weights_time_data), utils::castInputData<float>(bias_data),
188 utils::castOutputData<float>(activation_state_data),
189 utils::castOutputData<float>(scratch_buffer), utils::castOutputData<float>(output_data),
190 rank, input_size, batch_size, num_filters, num_units, memory_size,
191 options->fused_activation_function());
192
194 }
195 break;
196#endif // DIS_FLOAT
197#ifndef DIS_QUANT
198 case circle::TensorType_INT8:
199 {
200 core::SVDFQuantParams params{};
201 prepareQuantParams(params, input, weights_feature, weights_time, activation_state, output);
202
203 params.rank = rank;
204
205 status = pal::SVDF(
206 params, utils::castInputData<int8_t>(input_data),
207 utils::castInputData<int8_t>(weights_feature_data),
208 utils::castInputData<int8_t>(weights_time_data), utils::castInputData<int32_t>(bias_data),
209 utils::castOutputData<int8_t>(activation_state_data),
210 utils::castOutputData<int8_t>(output_data), input_shape, weights_feature_shape,
211 weights_time_shape, core::OMRuntimeShape(bias), output_shape);
212 }
213 break;
214#endif // DIS_QUANT
215 default:
216 {
217 status = UnsupportedActivation;
218 assert(false && "Unsupported type.");
219 break;
220 }
221 }
222
223 status = core::memory::OMMemoryManager::deallocateMemory(activation_state_data);
224
225 return status;
226}
227
228} // namespace execute
229} // namespace onert_micro
uint8_t * outputs_data[maxOutputSize]
const circle::Operator * first_operator
OMStatus getDataFromStorage(uint16_t op_index, core::OMRuntimeStorage &storage, core::OMRuntimeContext &context)
OMStatus readKernel(uint16_t op_index, core::OMRuntimeContext &runtime_context)
const circle::Tensor * outputs[maxOutputSize]
const circle::Tensor * inputs[maxInputSize]
const luci_interpreter::RuntimeShape output_shape
constexpr uint32_t outputTensorIdx
OMDataType
"scalar" value type
Definition OMDataType.h:35
OMStatus SVDF(const core::SVDFQuantParams &params, const int8_t *input_data, const int8_t *weights_feature_data, const int8_t *weights_time_data, const int32_t *bias_data, int8_t *state_data, int8_t *output_data, const core::OMRuntimeShape &input_shape, const core::OMRuntimeShape &weights_feature_shape, const core::OMRuntimeShape &weights_time_shape, const core::OMRuntimeShape &bias_shape, const core::OMRuntimeShape &output_shape)
Definition PALSVDF.h:35
void quantizeMultiplier(double double_multiplier, int32_t *quantized_multiplier, int *shift)
Definition OMUtils.cpp:23
OMStatus execute_kernel_CircleSVDF(const OMExecuteArgs &execute_args)
Definition SVDF.cpp:84
@ UnsupportedActivation
Definition OMStatus.h:28
static OMStatus deallocateMemory(uint8_t *data)
static OMStatus allocateMemory(uint32_t size, uint8_t **data)
core::OMRuntimeContext & runtime_context
core::OMRuntimeStorage & runtime_storage