1 /* Copyright 2020 The TensorFlow Authors. 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 "tensorflow/lite/delegates/gpu/common/selectors/simple_selectors.h"
17
18 #include <memory>
19 #include <set>
20 #include <utility>
21
22 #include "absl/memory/memory.h"
23 #include "tensorflow/lite/delegates/gpu/common/status.h"
24 #include "tensorflow/lite/delegates/gpu/common/tasks/add.h"
25 #include "tensorflow/lite/delegates/gpu/common/tasks/cast.h"
26 #include "tensorflow/lite/delegates/gpu/common/tasks/concat_xy.h"
27 #include "tensorflow/lite/delegates/gpu/common/tasks/concat_z.h"
28 #include "tensorflow/lite/delegates/gpu/common/tasks/cumsum.h"
29 #include "tensorflow/lite/delegates/gpu/common/tasks/depthwise_conv.h"
30 #include "tensorflow/lite/delegates/gpu/common/tasks/gather.h"
31 #include "tensorflow/lite/delegates/gpu/common/tasks/lstm.h"
32 #include "tensorflow/lite/delegates/gpu/common/tasks/max_unpooling.h"
33 #include "tensorflow/lite/delegates/gpu/common/tasks/one_hot.h"
34 #include "tensorflow/lite/delegates/gpu/common/tasks/padding.h"
35 #include "tensorflow/lite/delegates/gpu/common/tasks/pooling.h"
36 #include "tensorflow/lite/delegates/gpu/common/tasks/prelu.h"
37 #include "tensorflow/lite/delegates/gpu/common/tasks/quantize_and_dequantize.h"
38 #include "tensorflow/lite/delegates/gpu/common/tasks/reduce.h"
39 #include "tensorflow/lite/delegates/gpu/common/tasks/relu.h"
40 #include "tensorflow/lite/delegates/gpu/common/tasks/resampler.h"
41 #include "tensorflow/lite/delegates/gpu/common/tasks/reshape.h"
42 #include "tensorflow/lite/delegates/gpu/common/tasks/reshapex4.h"
43 #include "tensorflow/lite/delegates/gpu/common/tasks/resize.h"
44 #include "tensorflow/lite/delegates/gpu/common/tasks/select_v2.h"
45 #include "tensorflow/lite/delegates/gpu/common/tasks/softmax.h"
46 #include "tensorflow/lite/delegates/gpu/common/tasks/softmax1x1.h"
47 #include "tensorflow/lite/delegates/gpu/common/tasks/space_to_depth.h"
48 #include "tensorflow/lite/delegates/gpu/common/tasks/split.h"
49 #include "tensorflow/lite/delegates/gpu/common/tasks/strided_slice.h"
50 #include "tensorflow/lite/delegates/gpu/common/tasks/tile.h"
51 #include "tensorflow/lite/delegates/gpu/common/tasks/transpose.h"
52 #include "tensorflow/lite/delegates/gpu/common/tasks/winograd.h"
53
54 namespace tflite {
55 namespace gpu {
56
SelectLSTM(const OperationDef & op_def,const GpuInfo & gpu_info)57 std::unique_ptr<GPUOperation> SelectLSTM(const OperationDef& op_def,
58 const GpuInfo& gpu_info) {
59 return std::make_unique<GPUOperation>(CreateLSTM(op_def, gpu_info));
60 }
61
SelectReLU(const ReLUAttributes & attr,const OperationDef & op_def)62 std::unique_ptr<GPUOperation> SelectReLU(const ReLUAttributes& attr,
63 const OperationDef& op_def) {
64 return std::make_unique<GPUOperation>(CreateReLU(op_def, attr));
65 }
66
SelectPReLU(const PReLUAttributes & attr,const GpuInfo & gpu_info,const OperationDef & op_def)67 std::unique_ptr<GPUOperation> SelectPReLU(const PReLUAttributes& attr,
68 const GpuInfo& gpu_info,
69 const OperationDef& op_def) {
70 return std::make_unique<GPUOperation>(CreatePReLU(gpu_info, op_def, attr));
71 }
72
SelectPooling(const Pooling2DAttributes & attr,const GpuInfo & gpu_info,const OperationDef & op_def)73 std::unique_ptr<GPUOperation> SelectPooling(const Pooling2DAttributes& attr,
74 const GpuInfo& gpu_info,
75 const OperationDef& op_def) {
76 return std::make_unique<GPUOperation>(CreatePooling(op_def, gpu_info, attr));
77 }
78
SelectMaxUnpooling(const MaxUnpooling2DAttributes & attr,const GpuInfo & gpu_info,const OperationDef & op_def)79 std::unique_ptr<GPUOperation> SelectMaxUnpooling(
80 const MaxUnpooling2DAttributes& attr, const GpuInfo& gpu_info,
81 const OperationDef& op_def) {
82 return std::make_unique<GPUOperation>(
83 CreateMaxUnpooling(gpu_info, op_def, attr));
84 }
85
SelectAdd(const OperationDef & op_def,const std::vector<int> & channels,int dst_channels,std::unique_ptr<GPUOperation> * ptr)86 void SelectAdd(const OperationDef& op_def, const std::vector<int>& channels,
87 int dst_channels, std::unique_ptr<GPUOperation>* ptr) {
88 GPUOperation operation = CreateAdd(op_def, channels, dst_channels);
89 *ptr = std::make_unique<GPUOperation>(std::move(operation));
90 }
91
SelectGather(const GatherAttributes & attr,const OperationDef & op_def,std::unique_ptr<GPUOperation> * ptr)92 absl::Status SelectGather(const GatherAttributes& attr,
93 const OperationDef& op_def,
94 std::unique_ptr<GPUOperation>* ptr) {
95 if (attr.axis != Axis::WIDTH) {
96 return absl::UnimplementedError(
97 "No gather for this axis. Only Width axis supported.");
98 }
99 GPUOperation operation = CreateGather(op_def, attr);
100 *ptr = std::make_unique<GPUOperation>(std::move(operation));
101 return absl::OkStatus();
102 }
103
SelectResampler(const OperationDef & op_def,const GpuInfo & gpu_info)104 std::unique_ptr<GPUOperation> SelectResampler(const OperationDef& op_def,
105 const GpuInfo& gpu_info) {
106 GPUOperation operation = CreateResampler(gpu_info, op_def);
107 return std::make_unique<GPUOperation>(std::move(operation));
108 }
109
SelectResize(const Resize2DAttributes & attr,const OperationDef & op_def,std::unique_ptr<GPUOperation> * ptr)110 absl::Status SelectResize(const Resize2DAttributes& attr,
111 const OperationDef& op_def,
112 std::unique_ptr<GPUOperation>* ptr) {
113 Resize operation = CreateResize(op_def, attr);
114 *ptr = std::make_unique<Resize>(std::move(operation));
115 return absl::OkStatus();
116 }
117
SelectConcat(const ConcatAttributes & attr,const std::vector<int> & channels,const OperationDef & op_def,const GpuInfo & gpu_info,std::unique_ptr<GPUOperation> * ptr)118 absl::Status SelectConcat(const ConcatAttributes& attr,
119 const std::vector<int>& channels,
120 const OperationDef& op_def, const GpuInfo& gpu_info,
121 std::unique_ptr<GPUOperation>* ptr) {
122 switch (attr.axis) {
123 case Axis::CHANNELS: {
124 GPUOperation operation = CreateConcatZ(op_def, channels, gpu_info);
125 *ptr = std::make_unique<GPUOperation>(std::move(operation));
126 return absl::OkStatus();
127 }
128 case Axis::BATCH:
129 case Axis::DEPTH:
130 case Axis::HEIGHT:
131 case Axis::WIDTH: {
132 GPUOperation operation = CreateConcatXY(op_def, attr);
133 *ptr = std::make_unique<GPUOperation>(std::move(operation));
134 return absl::OkStatus();
135 }
136 default:
137 return absl::UnimplementedError("No concat for this axis.");
138 }
139 }
140
SelectDWConvolutionDynamicWeights(const DepthwiseConvolution2DAttributes & attr,const GpuInfo & gpu_info,const OperationDef & op_def)141 std::unique_ptr<GPUOperation> SelectDWConvolutionDynamicWeights(
142 const DepthwiseConvolution2DAttributes& attr, const GpuInfo& gpu_info,
143 const OperationDef& op_def) {
144 return std::make_unique<DepthwiseConv>(
145 CreateDepthwiseConvolution2DDynamicWeights(gpu_info, op_def, attr));
146 }
147
SelectReshape(int src_channels,int dst_channels,const OperationDef & op_def,std::unique_ptr<GPUOperation> * ptr)148 void SelectReshape(int src_channels, int dst_channels,
149 const OperationDef& op_def,
150 std::unique_ptr<GPUOperation>* ptr) {
151 if (src_channels % 4 == 0 && dst_channels % 4 == 0) {
152 GPUOperation operation = CreateReshapex4(op_def);
153 *ptr = std::make_unique<GPUOperation>(std::move(operation));
154 } else {
155 GPUOperation operation = CreateReshape(op_def);
156 *ptr = std::make_unique<GPUOperation>(std::move(operation));
157 }
158 }
159
SelectSpaceToDepth(const SpaceToDepthAttributes & attr,const OperationDef & op_def,std::unique_ptr<GPUOperation> * ptr)160 void SelectSpaceToDepth(const SpaceToDepthAttributes& attr,
161 const OperationDef& op_def,
162 std::unique_ptr<GPUOperation>* ptr) {
163 GPUOperation operation = CreateSpaceToDepth(op_def, attr);
164 *ptr = std::make_unique<GPUOperation>(std::move(operation));
165 }
166
SelectDepthToSpace(const SpaceToDepthAttributes & attr,const OperationDef & op_def,std::unique_ptr<GPUOperation> * ptr)167 void SelectDepthToSpace(const SpaceToDepthAttributes& attr,
168 const OperationDef& op_def,
169 std::unique_ptr<GPUOperation>* ptr) {
170 GPUOperation operation = CreateDepthToSpace(op_def, attr);
171 *ptr = std::make_unique<GPUOperation>(std::move(operation));
172 }
173
SelectSplit(const SplitAttributes & attr,const GpuInfo & gpu_info,const std::vector<int> & channels,const OperationDef & op_def,std::unique_ptr<GPUOperation> * ptr)174 void SelectSplit(const SplitAttributes& attr, const GpuInfo& gpu_info,
175 const std::vector<int>& channels, const OperationDef& op_def,
176 std::unique_ptr<GPUOperation>* ptr) {
177 Split operation = CreateSplit(gpu_info, op_def, attr, channels);
178 *ptr = std::make_unique<Split>(std::move(operation));
179 }
180
SelectPadding(const PadAttributes & attr,const OperationDef & op_def,std::unique_ptr<GPUOperation> * ptr)181 void SelectPadding(const PadAttributes& attr, const OperationDef& op_def,
182 std::unique_ptr<GPUOperation>* ptr) {
183 GPUOperation operation = CreatePadding(op_def, attr);
184 *ptr = std::make_unique<GPUOperation>(std::move(operation));
185 }
186
SelectStridedSlice(const SliceAttributes & attr,const OperationDef & op_def,std::unique_ptr<GPUOperation> * ptr)187 void SelectStridedSlice(const SliceAttributes& attr, const OperationDef& op_def,
188 std::unique_ptr<GPUOperation>* ptr) {
189 StridedSlice operation = CreateStridedSlice(op_def, attr);
190 *ptr = std::make_unique<StridedSlice>(std::move(operation));
191 }
192
SelectReduce(const std::set<Axis> & axis_to_reduce,const BHWC & src_shape,OperationType op_type,const OperationDef & op_def,const GpuInfo & gpu_info)193 std::unique_ptr<GPUOperation> SelectReduce(const std::set<Axis>& axis_to_reduce,
194 const BHWC& src_shape,
195 OperationType op_type,
196 const OperationDef& op_def,
197 const GpuInfo& gpu_info) {
198 return std::make_unique<Reduce>(
199 CreateReduce(axis_to_reduce, src_shape, op_type, op_def, gpu_info));
200 }
201
SelectSoftmax(const BHWC & shape,const OperationDef & op_def,std::unique_ptr<GPUOperation> * ptr)202 void SelectSoftmax(const BHWC& shape, const OperationDef& op_def,
203 std::unique_ptr<GPUOperation>* ptr) {
204 if (shape.w == 1 && shape.h == 1) {
205 Softmax1x1 operation = CreateSoftmax1x1(op_def);
206 *ptr = std::make_unique<Softmax1x1>(std::move(operation));
207 } else {
208 GPUOperation operation = CreateSoftmax(op_def);
209 *ptr = std::make_unique<GPUOperation>(std::move(operation));
210 }
211 }
212
SelectTile(const OperationDef & op_def,const BHWC & src_shape)213 std::unique_ptr<GPUOperation> SelectTile(const OperationDef& op_def,
214 const BHWC& src_shape) {
215 return std::make_unique<GPUOperation>(CreateTile(op_def, src_shape.c));
216 }
217
SelectTranspose(const TransposeAttributes & attr,const OperationDef & op_def,std::unique_ptr<GPUOperation> * ptr)218 void SelectTranspose(const TransposeAttributes& attr,
219 const OperationDef& op_def,
220 std::unique_ptr<GPUOperation>* ptr) {
221 GPUOperation operation = CreateTranspose(op_def, attr);
222 *ptr = std::make_unique<GPUOperation>(std::move(operation));
223 }
224
SelectWinograd4x4To36(const GpuInfo & gpu_info,const Padding2D & padding,const OperationDef & op_def)225 std::unique_ptr<GPUOperation> SelectWinograd4x4To36(
226 const GpuInfo& gpu_info, const Padding2D& padding,
227 const OperationDef& op_def) {
228 if (gpu_info.IsApple() || gpu_info.IsAMD()) {
229 Winograd4x4To36 operation =
230 CreateWinograd4x4To36(op_def, padding, gpu_info);
231 return std::make_unique<Winograd4x4To36>(std::move(operation));
232 }
233 return std::make_unique<Winograd4x4To36TileX6>(
234 CreateWinograd4x4To36TileX6(gpu_info, op_def, padding));
235 }
236
SelectWinograd36To4x4(const GpuInfo & gpu_info,const OperationDef & op_def,const tflite::gpu::Tensor<Linear,DataType::FLOAT32> & biases)237 std::unique_ptr<GPUOperation> SelectWinograd36To4x4(
238 const GpuInfo& gpu_info, const OperationDef& op_def,
239 const tflite::gpu::Tensor<Linear, DataType::FLOAT32>& biases) {
240 if (gpu_info.IsApple() || gpu_info.IsAMD()) {
241 Winograd36To4x4 operation = CreateWinograd36To4x4(op_def, biases);
242 return std::make_unique<Winograd36To4x4>(std::move(operation));
243 }
244 return std::make_unique<Winograd36To4x4Tile4x1>(
245 CreateWinograd36To4x4Tile4x1(gpu_info, op_def, biases));
246 }
247
SelectQuantizeAndDequantize(const QuantizeAndDequantizeAttributes & attr,const OperationDef & op_def)248 std::unique_ptr<GPUOperation> SelectQuantizeAndDequantize(
249 const QuantizeAndDequantizeAttributes& attr, const OperationDef& op_def) {
250 return std::make_unique<GPUOperation>(
251 CreateQuantizeAndDequantize(op_def, attr));
252 }
253
SelectCast(const OperationDef & op_def,const GpuInfo & gpu_info,std::unique_ptr<GPUOperation> * ptr)254 void SelectCast(const OperationDef& op_def, const GpuInfo& gpu_info,
255 std::unique_ptr<GPUOperation>* ptr) {
256 GPUOperation operation = CreateCast(op_def, gpu_info);
257 *ptr = std::make_unique<GPUOperation>(std::move(operation));
258 }
259
SelectCumsum(const OperationDef & op_def,const CumsumAttributes & attr,std::unique_ptr<GPUOperation> * ptr)260 void SelectCumsum(const OperationDef& op_def, const CumsumAttributes& attr,
261 std::unique_ptr<GPUOperation>* ptr) {
262 Cumsum operation = CreateCumsum(op_def, attr);
263 *ptr = std::make_unique<Cumsum>(std::move(operation));
264 }
265
SelectOneHot(const OperationDef & op_def,const OneHotAttributes & attr,std::unique_ptr<GPUOperation> * ptr)266 void SelectOneHot(const OperationDef& op_def, const OneHotAttributes& attr,
267 std::unique_ptr<GPUOperation>* ptr) {
268 GPUOperation operation = CreateOneHot(op_def, attr);
269 *ptr = std::make_unique<GPUOperation>(std::move(operation));
270 }
271
SelectSelectV2(const OperationDef & op_def,const SelectV2Attributes & attr,std::unique_ptr<GPUOperation> * ptr)272 void SelectSelectV2(const OperationDef& op_def, const SelectV2Attributes& attr,
273 std::unique_ptr<GPUOperation>* ptr) {
274 GPUOperation operation = CreateSelectV2(op_def, attr);
275 *ptr = std::make_unique<GPUOperation>(std::move(operation));
276 }
277
278 } // namespace gpu
279 } // namespace tflite
280