ONE - On-device Neural Engine
Loading...
Searching...
No Matches
SVDF.cpp
Go to the documentation of this file.
1/*
2 * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
3 * Copyright 2017 The TensorFlow Authors. All Rights Reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#include "Builders.h"
19#include "kernels/Utils.h"
20
21#include "PALSVDF.h"
22
23namespace luci_interpreter
24{
25
26namespace
27{
28const int kSvdfInputTensor = 0;
29const int kSvdfWeightsFeatureTensor = 1;
30const int kSvdfWeightsTimeTensor = 2;
31const int kSvdfBiasTensor = 3;
32const int kSvdfInputActivationStateTensor =
33 4; // This is a variable tensor, and will be modified by this op.
34const int kSvdfOutputTensor = 0;
35} // namespace
36
37void configure_kernel_CircleSVDF(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
38{
39 // Validate Tensor Inputs (dtype depends on quantization):
40 // [0] = Input, {2, batch_size, input_size}
41 // [1] = Weights Feature, {2, num_filters, input_size}
42 // [2] = Weights Time, {2, num_filters, memory_size}
43 // [3] = Bias (optional), {1, num_units}
44 // [4] = Activation State (variable),
45 // {2, batch_size, memory_size * num_filters}
46 const auto input_index = cur_op->inputs()->operator[](kSvdfInputTensor);
47 const auto weights_feature_index = cur_op->inputs()->operator[](kSvdfWeightsFeatureTensor);
48 const auto weights_time_index = cur_op->inputs()->operator[](kSvdfWeightsTimeTensor);
49 const auto bias_index = cur_op->inputs()->operator[](kSvdfBiasTensor);
50 const auto activation_state_index = cur_op->inputs()->operator[](kSvdfInputActivationStateTensor);
51 const auto output_index = cur_op->outputs()->operator[](kSvdfOutputTensor);
52
53 assert(input_index != -1);
54 assert(weights_feature_index != -1);
55 assert(weights_time_index != -1);
56 assert(activation_state_index != -1);
57 assert(output_index != -1);
58
59 const auto input = runtime_graph->getCircleTensorByIndex(input_index);
60 const auto weights_feature = runtime_graph->getCircleTensorByIndex(weights_feature_index);
61 const auto weights_time = runtime_graph->getCircleTensorByIndex(weights_time_index);
62 const auto bias = runtime_graph->getCircleTensorByIndex(bias_index);
63 const auto activation_state = runtime_graph->getCircleTensorByIndex(activation_state_index);
64 const auto output = runtime_graph->getCircleTensorByIndex(output_index);
65
66 assert(input != nullptr);
67 assert(weights_feature != nullptr);
68 assert(weights_time != nullptr);
69 assert(activation_state != nullptr);
70 assert(output != nullptr);
71
72 const auto *options = cur_op->builtin_options_as_SVDFOptions();
73
74 // Define input constants based on input tensor definition above:
75 const int rank = options->rank();
76 const int input_size = Tensor::dim(input, 1);
77 const int batch_size = Tensor::dim(input, 0);
78 const int num_filters = Tensor::dim(weights_feature, 0);
79 LUCI_INTERPRETER_CHECK(num_filters % rank == 0);
80
81 const int num_units = num_filters / rank;
82 const int memory_size = Tensor::dim(weights_time, 1);
83
84 LUCI_INTERPRETER_CHECK(Tensor::element_type(input) == DataType::FLOAT32 or
85 Tensor::element_type(input) == DataType::S8);
86 LUCI_INTERPRETER_CHECK(Tensor::num_dims(input) == 2);
87
88 // Validate Tensor Output:
89 // [0] = float/int8_t, {2, batch_size, num_units}
90 LUCI_INTERPRETER_CHECK(Tensor::num_dims(output) == 2);
91 LUCI_INTERPRETER_CHECK(Tensor::dim(output, 0) == batch_size);
92 LUCI_INTERPRETER_CHECK(Tensor::dim(output, 1) == num_units);
93
94 // Validate Weights Feature Input Tensor
95 LUCI_INTERPRETER_CHECK(Tensor::num_dims(weights_feature) == 2);
96 LUCI_INTERPRETER_CHECK(Tensor::dim(weights_feature, 1) == input_size);
97
98 // Validate Weights Time Input Tensor:
99 LUCI_INTERPRETER_CHECK(Tensor::num_dims(weights_time) == 2);
100 LUCI_INTERPRETER_CHECK(Tensor::dim(weights_time, 0) == num_filters);
101 LUCI_INTERPRETER_CHECK(Tensor::dim(weights_time, 1) == memory_size);
102
103 // Validate Optional Bias Input Tensor:
104 if (bias != nullptr)
105 {
106 LUCI_INTERPRETER_CHECK(Tensor::dim(bias, 0) == num_units);
107 }
108
109 // Validate Activation State Input Tensor:
110 LUCI_INTERPRETER_CHECK(Tensor::num_dims(activation_state) == 2);
111 LUCI_INTERPRETER_CHECK(Tensor::dim(activation_state, 0) == batch_size);
112 LUCI_INTERPRETER_CHECK(Tensor::dim(activation_state, 1) == memory_size * num_filters);
113
114 if (Tensor::element_type(input) == DataType::FLOAT32)
115 {
116 LUCI_INTERPRETER_CHECK(Tensor::element_type(weights_feature) == DataType::FLOAT32);
117 LUCI_INTERPRETER_CHECK(Tensor::element_type(weights_time) == DataType::FLOAT32);
118 LUCI_INTERPRETER_CHECK(Tensor::element_type(activation_state) == DataType::FLOAT32);
119 if (bias)
120 LUCI_INTERPRETER_CHECK(Tensor::element_type(bias) == DataType::FLOAT32);
121 LUCI_INTERPRETER_CHECK(Tensor::element_type(output) == DataType::FLOAT32);
122 }
123}
124
125void execute_kernel_CircleSVDF(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
126{
127 const auto input_index = cur_op->inputs()->operator[](kSvdfInputTensor);
128 const auto weights_feature_index = cur_op->inputs()->operator[](kSvdfWeightsFeatureTensor);
129 const auto weights_time_index = cur_op->inputs()->operator[](kSvdfWeightsTimeTensor);
130 const auto bias_index = cur_op->inputs()->operator[](kSvdfBiasTensor);
131 const auto activation_state_index = cur_op->inputs()->operator[](kSvdfInputActivationStateTensor);
132 const auto output_index = cur_op->outputs()->operator[](kSvdfOutputTensor);
133
134 assert(input_index != -1);
135 assert(weights_feature_index != -1);
136 assert(weights_time_index != -1);
137 assert(activation_state_index != -1);
138 assert(output_index != -1);
139
140 const auto input = runtime_graph->getCircleTensorByIndex(input_index);
141 const auto weights_feature = runtime_graph->getCircleTensorByIndex(weights_feature_index);
142 const auto weights_time = runtime_graph->getCircleTensorByIndex(weights_time_index);
143 const auto bias = runtime_graph->getCircleTensorByIndex(bias_index);
144 const auto activation_state = runtime_graph->getCircleTensorByIndex(activation_state_index);
145 const auto output = runtime_graph->getCircleTensorByIndex(output_index);
146
147 assert(input != nullptr);
148 assert(weights_feature != nullptr);
149 assert(weights_time != nullptr);
150 assert(activation_state != nullptr);
151 assert(output != nullptr);
152
153 const auto *options = cur_op->builtin_options_as_SVDFOptions();
154
155 // Define input constants based on input tensor definition above:
156 const int rank = options->rank();
157 const int input_size = Tensor::dim(input, 1);
158 const int batch_size = Tensor::dim(input, 0);
159 const int num_filters = Tensor::dim(weights_feature, 0);
160 LUCI_INTERPRETER_CHECK(num_filters % rank == 0);
161
162 const int num_units = num_filters / rank;
163 const int memory_size = Tensor::dim(weights_time, 1);
164
165 const uint8_t *input_data = runtime_graph->getDataByTensor(input);
166 const uint8_t *weights_feature_data = runtime_graph->getConstDataByTensor(weights_feature);
167 const uint8_t *weights_time_data = runtime_graph->getConstDataByTensor(weights_time);
168 const uint8_t *bias_data = runtime_graph->getConstDataByTensor(bias);
169 uint8_t *output_data = runtime_graph->getDataByTensor(output);
170
171 const auto type = Tensor::element_type(input);
172 switch (type)
173 {
174#ifndef DIS_FLOAT
175 case DataType::FLOAT32:
176 {
177 // Create and fill with 0 state tensor
178 auto state_data = std::make_unique<float[]>(Tensor::num_elements(activation_state));
179 std::fill_n(state_data.get(), Tensor::num_elements(activation_state), 0);
180
181 auto scratch_data = std::make_unique<uint8_t[]>(batch_size * num_filters * sizeof(float));
182
184 kernels::getTensorData<float>(input_data),
185 kernels::getTensorData<float>(weights_feature_data),
186 kernels::getTensorData<float>(weights_time_data), kernels::getTensorData<float>(bias_data),
187 state_data.get(), kernels::getTensorData<float>(scratch_data.get()),
188 kernels::getTensorData<float>(output_data), rank, input_size, batch_size, num_filters,
189 num_units, memory_size, options->fused_activation_function());
190 }
191 break;
192#endif // DIS_FLOAT
193 default:
194 assert(false && "Unsupported type.");
195 }
196}
197
198} // namespace luci_interpreter
uint8_t * getConstDataByTensor(const circle::Tensor *raw_tensor)
const circle::Tensor * getCircleTensorByIndex(int32_t index)
uint8_t * getDataByTensor(const circle::Tensor *raw_tensor)
#define LUCI_INTERPRETER_CHECK(cond)
Definition Utils.h:36
void SVDF(const float *input_data, const float *weights_feature_data, const float *weights_time_data, const float *bias_data, float *state_data, float *scratch_data, float *output_data, const int rank, const int input_size, const int batch_size, const int num_filters, const int num_units, const int memory_size, const circle::ActivationFunctionType activation)
void configure_kernel_CircleSVDF(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
Definition SVDF.cpp:37
void execute_kernel_CircleSVDF(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
Definition SVDF.cpp:125
const loco::Dimension & dim(uint32_t axis) const
Definition Tensor.h:44