ONE - On-device Neural Engine
Loading...
Searching...
No Matches
DepthwiseConv2D.cpp
Go to the documentation of this file.
1/* Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "luci_compute/Types.h"
18
19#include "ConvertTypes.h"
20#include "ConvertValues.h"
21
22#include <tensorflow/lite/kernels/internal/reference/depthwiseconv_float.h>
23
24#include <cassert>
25#include <cstdint>
26
27namespace luci
28{
29namespace compute
30{
31
32namespace
33{
34
35int32_t compute_output(PaddingType padding, int32_t in_size, int32_t filter_size, int32_t stride,
36 int32_t dilation_rate)
37{
38 assert(in_size > 0);
39 assert(filter_size > 0);
40 assert(stride > 0);
41 assert(dilation_rate > 0);
42
43 auto const effective_filter_size = (filter_size - 1) * dilation_rate + 1;
44 switch (padding)
45 {
47 return (in_size + stride - 1) / stride;
48
50 return (in_size + stride - effective_filter_size) / stride;
51
52 default:
53 return -1;
54 }
55 return -1;
56}
57
58int16_t compute_padding(int32_t out_size, int32_t in_size, int32_t filter_size, int32_t stride,
59 int32_t dilation_rate)
60{
61 assert(out_size > 0);
62 assert(in_size > 0);
63 assert(filter_size > 0);
64 assert(stride > 0);
65 assert(dilation_rate > 0);
66
67 auto const effective_filter_size = (filter_size - 1) * dilation_rate + 1;
68 auto const padding = ((out_size - 1) * stride + effective_filter_size - in_size) / 2;
69 assert(padding < INT16_MAX);
70 return padding > 0 ? static_cast<int16_t>(padding) : 0;
71}
72
73} // namespace
74
76{
77 // TODO support other ranks if necessary
78 if (_input_shape.rank() != 4 || _filter_shape.rank() != 4)
79 return false;
80 // if bias exist, check if rank is 1
81 if (_bias_data && _bias_shape.rank() != 1)
82 return false;
83
84 auto const input_batches = _input_shape.dim(0).value();
85 auto const input_height = _input_shape.dim(1).value();
86 auto const input_width = _input_shape.dim(2).value();
87 auto const input_depth = _input_shape.dim(3).value();
88
89 auto const filter_height = _filter_shape.dim(1).value();
90 auto const filter_width = _filter_shape.dim(2).value();
91 auto const filter_channels_out = _filter_shape.dim(3).value();
92
93 if (filter_channels_out % input_depth != 0)
94 return false; // wrong input/output depth ratio
95
96 if (_params.depth_multiplier != static_cast<int32_t>(filter_channels_out / input_depth))
97 return false; // wrong depth multiplier value
98
99 if (_bias_shape.dim(0).value() != filter_channels_out)
100 return false; // unsupported bias value
101
102 auto output_height = compute_output(_params.padding_type, input_height, filter_height,
103 _params.stride_height, _params.dilation_height_factor);
104 if (output_height < 0)
105 return false;
106
107 auto output_width = compute_output(_params.padding_type, input_width, filter_width,
108 _params.stride_width, _params.dilation_width_factor);
109 if (output_width < 0)
110 return false;
111
112 get_act_minmax(_fused_act_func, _params.float_activation_min, _params.float_activation_max);
113
114 _output_shape.rank(4);
115 _output_shape.dim(0) = input_batches;
116 _output_shape.dim(1) = output_height;
117 _output_shape.dim(2) = output_width;
118 _output_shape.dim(3) = filter_channels_out;
119
120 _params.padding_values.height =
121 compute_padding(output_height, input_height, filter_height, _params.stride_height,
122 _params.dilation_height_factor);
123 _params.padding_values.width = compute_padding(
124 output_width, input_width, filter_width, _params.stride_width, _params.dilation_width_factor);
125
126 return true;
127}
128
130{
131 assert(_input_data != nullptr);
132 assert(_filter_data != nullptr);
133 // NOTE _bias_shape can be nullptr
134 assert(_output_data != nullptr);
135
136 // NOTE if this fails, structure may have changed
137 static_assert(sizeof(compute::DepthwiseParams) == sizeof(tflite::DepthwiseParams));
138
139 tflite::DepthwiseParams params;
140
141 // clang-format off
163 // clang-format on
164
165 tflite::reference_ops::DepthwiseConv(
166 params, tflite_shape(_input_shape), _input_data, tflite_shape(_filter_shape), _filter_data,
167 tflite_shape(_bias_shape), _bias_data, tflite_shape(_output_shape), _output_data);
168}
169
170} // namespace compute
171} // namespace luci
uint32_t value(void) const
Return the value.
Definition Dimension.h:51
const Dimension & dim(uint32_t axis) const
Definition TensorShape.h:38
uint32_t rank(void) const
Definition TensorShape.h:35
DepthwiseParams & params(void)
tflite::PaddingType tflite_padding(const PaddingType type)
void get_act_minmax(const FusedActFunc act, float &act_min, float &act_max)
tflite::RuntimeShape tflite_shape(const loco::TensorShape &shape)
PaddingValues padding_values
Definition Types.h:56
const int32_t * output_multiplier_per_channel
Definition Types.h:75
const int32_t * output_shift_per_channel
Definition Types.h:76