ONE - On-device Neural Engine
Loading...
Searching...
No Matches
TransposeConv.cpp
Go to the documentation of this file.
1/*
2 * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
3 * Copyright 2019 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 "PALTransposeConv.h"
22
23namespace luci_interpreter
24{
25
26namespace
27{
28
29// For the TfLite transpose_conv implementation, input tensor 0 corresponds to
30// the OutputShapeTensor. However, since TFLM does not support dynamic tensors,
31// the TFLM implementation ignores input tensor 0 and the only inputs we care
32// about are kFilterTensor, kInputTensor and kBiasTensor.
33constexpr int kFilterTensor = 1;
34constexpr int kInputTensor = 2;
35constexpr int kBiasTensor = 3;
36constexpr int kOutputTensor = 0;
37
38// TODO: reduce code duplication with Conv
39int32_t compute_padding_h(const circle::Tensor *input, const circle::Tensor *filter,
40 const circle::TransposeConvOptions *options)
41{
42 // Note: Dilation height and width are always 1 for transpose_conv
43 const int32_t input_height = Tensor::dim(input, 1);
44 const int32_t filter_height = Tensor::dim(filter, 1);
45 const int32_t output_height = kernels::computeOutputSize(
46 luci_padding(options->padding()), input_height, filter_height, options->stride_h(), 1);
47
48 const auto padding_height =
49 kernels::computePadding(options->stride_h(), 1, input_height, filter_height, output_height);
50 return padding_height;
51}
52
53int32_t compute_padding_w(const circle::Tensor *input, const circle::Tensor *filter,
54 const circle::TransposeConvOptions *options)
55{
56 // Note: Dilation height and width are always 1 for transpose_conv
57 const int32_t input_width = Tensor::dim(input, 2);
58 const int32_t filter_width = Tensor::dim(filter, 2);
59 const int32_t output_width = kernels::computeOutputSize(
60 luci_padding(options->padding()), input_width, filter_width, options->stride_w(), 1);
61
62 const auto padding_width =
63 kernels::computePadding(options->stride_w(), 1, input_width, filter_width, output_width);
64
65 return padding_width;
66}
67
68#ifndef DIS_FLOAT
69
70void evalFloat(const circle::Tensor *input, const circle::Tensor *filter,
71 const circle::Tensor *bias, const circle::Tensor *output,
72 const circle::TransposeConvOptions *options, BaseRuntimeGraph *runtime_graph)
73{
74 float activation_min{};
75 float activation_max{};
76 kernels::calculateActivationRange(FusedActFunc::NONE, &activation_min, &activation_max);
77
79 params.padding_values.height = compute_padding_h(input, filter, options);
80 params.padding_values.width = compute_padding_w(input, filter, options);
81 params.stride_height = options->stride_h();
82 params.stride_width = options->stride_w();
83 params.dilation_height_factor = 1;
84 params.dilation_width_factor = 1;
85 params.float_activation_min = activation_min;
86 params.float_activation_max = activation_max;
87
88 auto *input_data = runtime_graph->getDataByTensor(input);
89 auto *output_data = runtime_graph->getDataByTensor(output);
90
91 auto *filter_data = runtime_graph->getConstDataByTensor(filter);
92 auto *bias_data = runtime_graph->getConstDataByTensor(bias);
93
95 params, kernels::getTensorRuntimeShape(input, runtime_graph),
96 kernels::getTensorData<float>(input_data),
97 kernels::getTensorRuntimeShape(filter, runtime_graph),
98 kernels::getTensorData<float>(filter_data), kernels::getTensorRuntimeShape(bias, runtime_graph),
99 kernels::getTensorData<float>(bias_data), kernels::getTensorRuntimeShape(output, runtime_graph),
100 kernels::getTensorData<float>(output_data));
101}
102
103#endif // DIS_FLOAT
104
105} // namespace
106
107void configure_kernel_CircleTransposeConv(const circle::Operator *cur_op,
108 BaseRuntimeGraph *runtime_graph)
109{
110 const auto input_index = cur_op->inputs()->operator[](kInputTensor);
111 const auto filter_index = cur_op->inputs()->operator[](kFilterTensor);
112 const auto output_index = cur_op->outputs()->operator[](kOutputTensor);
113
114 assert(input_index != -1);
115 assert(filter_index != -1);
116 assert(output_index != -1);
117
118 const auto input = runtime_graph->getCircleTensorByIndex(input_index);
119 const auto filter = runtime_graph->getCircleTensorByIndex(filter_index);
120 const auto output = runtime_graph->getCircleTensorByIndex(output_index);
121
122 assert(input != nullptr);
123 assert(filter != nullptr);
124
125 auto filter_data = runtime_graph->getConstDataByTensor(filter);
126
127 assert(filter_data != nullptr);
128
129 LUCI_INTERPRETER_CHECK(Tensor::element_type(output) == Tensor::element_type(input));
130 LUCI_INTERPRETER_CHECK(Tensor::element_type(filter) == Tensor::element_type(input));
131
132 LUCI_INTERPRETER_CHECK(Tensor::num_dims(input) == 4 && Tensor::num_dims(filter) == 4);
133}
134
135void execute_kernel_CircleTransposeConv(const circle::Operator *cur_op,
136 BaseRuntimeGraph *runtime_graph)
137{
138 const auto input_index = cur_op->inputs()->operator[](kInputTensor);
139 const auto weight_index = cur_op->inputs()->operator[](kFilterTensor);
140 const auto bias_index =
141 cur_op->inputs()->size() == 4 ? cur_op->inputs()->operator[](kBiasTensor) : -1;
142 const auto output_index = cur_op->outputs()->operator[](kOutputTensor);
143
144 assert(input_index != -1);
145 assert(weight_index != -1);
146 assert(output_index != -1);
147
148 const auto input = runtime_graph->getCircleTensorByIndex(input_index);
149 const auto weights = runtime_graph->getCircleTensorByIndex(weight_index);
150 const auto bias = runtime_graph->getCircleTensorByIndex(bias_index);
151 const auto output = runtime_graph->getCircleTensorByIndex(output_index);
152
153 assert(input != nullptr);
154 assert(weights != nullptr);
155 assert(output != nullptr);
156
157 const auto *options = cur_op->builtin_options_as_TransposeConvOptions();
158
159 const auto type = Tensor::element_type(input);
160 switch (type)
161 {
162#ifndef DIS_FLOAT
163 case DataType::FLOAT32:
164 if (Tensor::element_type(weights) == DataType::FLOAT32)
165 {
166 evalFloat(input, weights, bias, output, options, runtime_graph);
167 break;
168 }
169#endif // DIS_FLOAT
170 default:
171 assert(false && "Unsupported type.");
172 }
173}
174
175} // namespace luci_interpreter
uint8_t * getConstDataByTensor(const circle::Tensor *raw_tensor)
const circle::Tensor * getCircleTensorByIndex(int32_t index)
#define LUCI_INTERPRETER_CHECK(cond)
Definition Utils.h:36
list input_data
Definition infer.py:29
int32_t computePadding(int32_t stride, int32_t dilation_rate, int32_t in_size, int32_t filter_size, int32_t out_size)
Definition Utils.h:41
void calculateActivationRange(Activation activation, T *activation_min, T *activation_max)
Definition Utils.cpp:52
int32_t computeOutputSize(Padding padding, int32_t image_size, int32_t filter_size, int32_t stride, int32_t dilation_rate=1)
Definition Utils.h:59
luci_interpreter::RuntimeShape getTensorRuntimeShape(const circle::Tensor *circle_tensor, BaseRuntimeGraph *runtime_graph)
Definition Utils.cpp:29
void TransposeConv(const ConvParams &params, const luci_interpreter::RuntimeShape &input_shape, const float *input_data, const luci_interpreter::RuntimeShape &filter_shape, const float *filter_data, const luci_interpreter::RuntimeShape &bias_shape, const float *bias_data, const luci_interpreter::RuntimeShape &output_shape, float *output_data)
RuntimeGraph BaseRuntimeGraph
void execute_kernel_CircleTransposeConv(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
void configure_kernel_CircleTransposeConv(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
Padding luci_padding(const circle::Padding padding)
const loco::Dimension & dim(uint32_t axis) const
Definition Tensor.h:44