ONE - On-device Neural Engine
Loading...
Searching...
No Matches
Conv.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
3 * Copyright 2015 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#ifndef __NNFW_CKER_TRAIN_OPERATION_CONV_H__
19#define __NNFW_CKER_TRAIN_OPERATION_CONV_H__
20
24#include "cker/eigen/Utils.h"
25#include "cker/Shape.h"
26#include "cker/Types.h"
27
28namespace nnfw
29{
30namespace cker
31{
32namespace train
33{
34
35// From tensorflow/core/kernels/conv_2d.h
36namespace functor
37{
38
39template <typename Device, typename T> struct SpatialConvolutionBackwardInputFunc
40{
41 void operator()(const Device &d, typename TTypes<T, 4>::Tensor input_backward,
42 typename TTypes<T, 4>::ConstTensor filter,
43 typename TTypes<T, 4>::ConstTensor output_backward, Eigen::DenseIndex col_stride,
44 Eigen::DenseIndex row_stride, Eigen::DenseIndex col_dilation,
45 Eigen::DenseIndex row_dilation)
46 {
47 input_backward.device(d) = Eigen::SpatialConvolutionBackwardInput(
48 filter, output_backward, input_backward.dimension(2), input_backward.dimension(1), col_stride,
49 row_stride, col_dilation, row_dilation);
50 }
51};
52
53template <typename Device, typename T> struct SpatialConvolutionBackwardInputWithExplicitPaddingFunc
54{
55 void operator()(const Device &d, typename TTypes<T, 4>::Tensor input_backward,
56 typename TTypes<T, 4>::ConstTensor filter,
57 typename TTypes<T, 4>::ConstTensor output_backward, Eigen::DenseIndex padded_cols,
58 Eigen::DenseIndex padded_rows, Eigen::DenseIndex col_stride,
59 Eigen::DenseIndex row_stride, Eigen::DenseIndex col_dilation,
60 Eigen::DenseIndex row_dilation, Eigen::DenseIndex pad_left,
61 Eigen::DenseIndex pad_top)
62 {
63 // We have to slice the result of a spatial convolution backward
64 // input, before assigning it to the `input_backward` to remove padding.
65 //
66 // TODO(ezhulenev): Pass explicit paddings to Eigen and do not materialize
67 // intermediate result in memory before slicing.
68 input_backward.device(d) =
69 Eigen::SpatialConvolutionBackwardInput(filter, output_backward, padded_cols, padded_rows,
70 col_stride, row_stride, col_dilation, row_dilation)
71 .eval()
72 .slice(Eigen::DSizes<Eigen::DenseIndex, 4>{0, pad_left, pad_top, 0},
73 input_backward.dimensions());
74 }
75};
76
77} // namespace functor
78
79// From tensorflow/core/kernels/conv_grad_input_ops.h
80// Computes backprop input using Eigen::SpatialConvolutionBackwardInput on CPU
81// and GPU (for int32 only).
82template <typename Device, typename T> struct LaunchConv2DBackpropInputOpImpl
83{
84 void operator()(const Device &d, const T *out_backprop_data, int batches, int out_backprop_height,
85 int out_backprop_width, int output_depth, const T *filter_data, int filter_height,
86 int filter_width, int row_dilation, int col_dilation, int row_stride /* H */,
87 int col_stride /* W */, const PaddingType &padding_type, int padding_top,
88 int padding_bottom, int padding_left, int padding_right, T *in_backprop_data,
89 int in_backprop_height, int in_backprop_width, int input_depth)
90 {
91 // WARNING: Need to swap row/col, padding_top/padding_left, and
92 // padding_bottom/padding_right when calling Eigen. Eigen expects tensors
93 // in NWHC format, but Tensorflow uses NHWC.
94
95 eigen_support::EigenTensor in_backprop_t(in_backprop_data, batches, in_backprop_height,
96 in_backprop_width, input_depth);
97 eigen_support::ConstEigenTensor filter_t(filter_data, filter_height, filter_width, input_depth,
98 output_depth);
99 eigen_support::ConstEigenTensor out_backprop_t(out_backprop_data, batches, out_backprop_height,
100 out_backprop_width, output_depth);
101
102 if (padding_type != PaddingType::kNone /* EXPLICIT */)
103 {
104 // If padding was not explicitly defined, Eigen spatial convolution
105 // backward input will infer correct forward paddings from input tensors.
107 d, in_backprop_t, filter_t, out_backprop_t, col_stride, row_stride, col_dilation,
108 row_dilation);
109 }
110 else
111 {
113 d, in_backprop_t, filter_t, out_backprop_t,
114 in_backprop_t.dimension(2) + (padding_left + padding_right),
115 in_backprop_t.dimension(1) + (padding_top + padding_bottom), col_stride, row_stride,
116 col_dilation, row_dilation, padding_top, padding_left);
117 }
118 }
119};
120
121// Computes backprop input using Eigen::SpatialConvolutionBackwardInput on CPU.
122template <typename T> struct LaunchConv2DBackpropInputOp
123{
124 void operator()(const T *out_backprop_data, int batches, int out_backprop_height,
125 int out_backprop_width, int output_depth, const T *filter_data, int filter_height,
126 int filter_width, int row_dilation, int col_dilation, int row_stride /* H */,
127 int col_stride /* W */, const PaddingType &padding_type, int padding_top,
128 int padding_bottom, int padding_left, int padding_right, T *in_backprop_data,
129 int in_backprop_height, int in_backprop_width, int input_depth)
130 {
132 launcher(*eigen_support::GetThreadPoolDevice(), out_backprop_data, batches, out_backprop_height,
133 out_backprop_width, output_depth, filter_data, filter_height, filter_width,
134 row_dilation, col_dilation, row_stride, col_stride, padding_type, padding_top,
135 padding_bottom, padding_left, padding_right, in_backprop_data, in_backprop_height,
136 in_backprop_width, input_depth);
137 }
138};
139
140// From tensorflow/core/kernels/conv_grad_filter_ops.cc
141template <typename T> struct LaunchConv2DBackpropFilterOp
142{
143 void operator()(const T *out_backprop_data, int batches, int out_backprop_height,
144 int out_backprop_width, int output_depth, const T *input_data, int input_height,
145 int input_width, int input_depth, int row_dilation, int col_dilation,
146 int row_stride /* H */, int col_stride /* W */, const PaddingType &padding_type,
147 int padding_top, int padding_bottom, int padding_left, int padding_right,
148 T *filter_backprop_data, int filter_backprop_height, int filter_backprop_width)
149 {
150 eigen_support::EigenTensor filter_backprop_t(filter_backprop_data, filter_backprop_height,
151 filter_backprop_width, input_depth, output_depth);
152 eigen_support::ConstEigenTensor input_t(input_data, batches, input_height, input_width,
153 input_depth);
154 eigen_support::ConstEigenTensor out_backprop_t(out_backprop_data, batches, out_backprop_height,
155 out_backprop_width, output_depth);
156
157 const Eigen::ThreadPoolDevice &d = *eigen_support::GetThreadPoolDevice();
158
159 if (padding_type != PaddingType::kNone /* EXPLICIT */)
160 {
161 // If padding was not explicitly defined, Eigen spatial convolution
162 // backward filter will infer correct forward paddings from input tensors.
163 filter_backprop_t.device(d) = Eigen::SpatialConvolutionBackwardKernel(
164 input_t, out_backprop_t, filter_backprop_t.dimension(1), filter_backprop_t.dimension(0),
165 col_stride, row_stride, col_dilation, row_dilation);
166 }
167 else
168 {
169 // Otherwise we have to explicitly pad the input, before passing it to
170 // spatial convolution backward filter.
171 Eigen::array<std::pair<int, int>, 4> paddings;
172 paddings[0] = {0, 0};
173 paddings[1] = {padding_top, padding_bottom};
174 paddings[2] = {padding_left, padding_right};
175 paddings[3] = {0, 0};
176
177 auto padded_t = input_t.pad(paddings, T(0));
178
179 // TODO(ezhulenev): Pass explicit paddings to Eigen spatial backward
180 // convolution and do not rely on tensor padding expression.
181 filter_backprop_t.device(d) = Eigen::SpatialConvolutionBackwardKernel(
182 padded_t, out_backprop_t, filter_backprop_t.dimension(1), filter_backprop_t.dimension(0),
183 col_stride, row_stride, col_dilation, row_dilation);
184 }
185 }
186};
187
188inline void ConvInputGrad(const ConvParams &params, const Shape &incoming_shape,
189 const float *incoming_data, const Shape &filter_shape,
190 const float *filter_data, const int padding_bottom,
191 const int padding_right, const Shape &grad_shape, float *grad_data)
192{
193 const int stride_rows = params.stride_height;
194 const int stride_cols = params.stride_width;
195 const PaddingType padding = params.padding_type;
196 const int padding_top = params.padding_values.height;
197 const int padding_left = params.padding_values.width;
198 assert(padding_top >= 0);
199 assert(padding_bottom >= 0);
200 assert(padding_left >= 0);
201 assert(padding_right >= 0);
202 const int dilation_rows = params.dilation_height_factor;
203 const int dilation_cols = params.dilation_width_factor;
204
205 const int batches = MatchingDim(grad_shape, 0, incoming_shape, 0);
206 const int input_depth = MatchingDim(filter_shape, 2, grad_shape, 3);
207 const int output_depth = MatchingDim(filter_shape, 3, incoming_shape, 3);
208 const int grad_height = grad_shape.Dims(1);
209 const int grad_width = grad_shape.Dims(2);
210 const int filter_height = filter_shape.Dims(0);
211 const int filter_width = filter_shape.Dims(1);
212 const int incoming_height = incoming_shape.Dims(1);
213 const int incoming_width = incoming_shape.Dims(2);
214
215 if (dilation_rows != 1 || dilation_cols != 1)
216 throw std::runtime_error("cker::ConvFilterGrad: not yet support dilation rates larger than 1.");
217
219 incoming_data, batches, incoming_height, incoming_width, output_depth, filter_data,
220 filter_height, filter_width, dilation_rows, dilation_cols, stride_rows, stride_cols, padding,
221 padding_top, padding_bottom, padding_left, padding_right, grad_data, grad_height, grad_width,
222 input_depth);
223}
224
225inline void ConvFilterGrad(const ConvParams &params, const Shape &incoming_shape,
226 const float *incoming_data, const Shape &input_shape,
227 const float *input_data, const int padding_bottom,
228 const int padding_right, const Shape &filter_backprop_shape,
229 float *filter_backprop_data)
230{
231 const int stride_rows = params.stride_height;
232 const int stride_cols = params.stride_width;
233 const PaddingType padding = params.padding_type;
234 const int padding_top = params.padding_values.height;
235 const int padding_left = params.padding_values.width;
236 assert(padding_top >= 0);
237 assert(padding_bottom >= 0);
238 assert(padding_left >= 0);
239 assert(padding_right >= 0);
240 const int dilation_rows = params.dilation_height_factor;
241 const int dilation_cols = params.dilation_width_factor;
242
243 const int batches = MatchingDim(input_shape, 0, incoming_shape, 0);
244 const int input_depth = MatchingDim(filter_backprop_shape, 2, input_shape, 3);
245 const int output_depth = MatchingDim(filter_backprop_shape, 3, incoming_shape, 3);
246 const int input_height = input_shape.Dims(1);
247 const int input_width = input_shape.Dims(2);
248 const int filter_backprop_height = filter_backprop_shape.Dims(0);
249 const int filter_backprop_width = filter_backprop_shape.Dims(1);
250 const int incoming_height = incoming_shape.Dims(1);
251 const int incoming_width = incoming_shape.Dims(2);
252
253 if (dilation_rows != 1 || dilation_cols != 1)
254 throw std::runtime_error("cker::ConvFilterGrad: not yet support dilation rates larger than 1.");
255
257 incoming_data, batches, incoming_height, incoming_width, output_depth, input_data, input_height,
258 input_width, input_depth, dilation_rows, dilation_cols, stride_rows, stride_cols, padding,
259 padding_top, padding_bottom, padding_left, padding_right, filter_backprop_data,
260 filter_backprop_height, filter_backprop_width);
261}
262
263} // namespace train
264} // namespace cker
265} // namespace nnfw
266
267#endif // __NNFW_CKER_TRAIN_OPERATION_RELU_H__
int32_t Dims(int i) const
Definition Shape.h:92
Eigen::TensorMap< Eigen::Tensor< float, 4, Eigen::RowMajor, Eigen::DenseIndex >, Eigen::Aligned > EigenTensor
const Eigen::ThreadPoolDevice * GetThreadPoolDevice()
Eigen::TensorMap< Eigen::Tensor< const float, 4, Eigen::RowMajor, Eigen::DenseIndex >, Eigen::Aligned > ConstEigenTensor
void ConvFilterGrad(const ConvParams &params, const Shape &incoming_shape, const float *incoming_data, const Shape &input_shape, const float *input_data, const int padding_bottom, const int padding_right, const Shape &filter_backprop_shape, float *filter_backprop_data)
Definition Conv.h:225
void ConvInputGrad(const ConvParams &params, const Shape &incoming_shape, const float *incoming_data, const Shape &filter_shape, const float *filter_data, const int padding_bottom, const int padding_right, const Shape &grad_shape, float *grad_data)
Definition Conv.h:188
int MatchingDim(const Shape &shape1, int index1, const Shape &shape2, int index2)
Definition Shape.h:220
PaddingType
Definition Types.h:41
Definition topk_v2.h:30
int16_t stride_height
Definition Types.h:146
PaddingValues padding_values
Definition Types.h:143
int16_t dilation_width_factor
Definition Types.h:147
PaddingType padding_type
Definition Types.h:142
int16_t dilation_height_factor
Definition Types.h:148
Eigen::TensorMap< Eigen::Tensor< const T, NDIMS, Eigen::RowMajor, IndexType >, Eigen::Aligned > ConstTensor
Definition Tensor.h:35
Eigen::TensorMap< Eigen::Tensor< T, NDIMS, Eigen::RowMajor, IndexType >, Eigen::Aligned > Tensor
Definition Tensor.h:32
void operator()(const T *out_backprop_data, int batches, int out_backprop_height, int out_backprop_width, int output_depth, const T *input_data, int input_height, int input_width, int input_depth, int row_dilation, int col_dilation, int row_stride, int col_stride, const PaddingType &padding_type, int padding_top, int padding_bottom, int padding_left, int padding_right, T *filter_backprop_data, int filter_backprop_height, int filter_backprop_width)
Definition Conv.h:143
void operator()(const T *out_backprop_data, int batches, int out_backprop_height, int out_backprop_width, int output_depth, const T *filter_data, int filter_height, int filter_width, int row_dilation, int col_dilation, int row_stride, int col_stride, const PaddingType &padding_type, int padding_top, int padding_bottom, int padding_left, int padding_right, T *in_backprop_data, int in_backprop_height, int in_backprop_width, int input_depth)
Definition Conv.h:124
void operator()(const Device &d, const T *out_backprop_data, int batches, int out_backprop_height, int out_backprop_width, int output_depth, const T *filter_data, int filter_height, int filter_width, int row_dilation, int col_dilation, int row_stride, int col_stride, const PaddingType &padding_type, int padding_top, int padding_bottom, int padding_left, int padding_right, T *in_backprop_data, int in_backprop_height, int in_backprop_width, int input_depth)
Definition Conv.h:84
void operator()(const Device &d, typename TTypes< T, 4 >::Tensor input_backward, typename TTypes< T, 4 >::ConstTensor filter, typename TTypes< T, 4 >::ConstTensor output_backward, Eigen::DenseIndex col_stride, Eigen::DenseIndex row_stride, Eigen::DenseIndex col_dilation, Eigen::DenseIndex row_dilation)
Definition Conv.h:41
void operator()(const Device &d, typename TTypes< T, 4 >::Tensor input_backward, typename TTypes< T, 4 >::ConstTensor filter, typename TTypes< T, 4 >::ConstTensor output_backward, Eigen::DenseIndex padded_cols, Eigen::DenseIndex padded_rows, Eigen::DenseIndex col_stride, Eigen::DenseIndex row_stride, Eigen::DenseIndex col_dilation, Eigen::DenseIndex row_dilation, Eigen::DenseIndex pad_left, Eigen::DenseIndex pad_top)
Definition Conv.h:55