• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
21 #include "absl/memory/memory.h"
22 #include "tensorflow/lite/delegates/gpu/common/status.h"
23 #include "tensorflow/lite/delegates/gpu/common/tasks/add.h"
24 #include "tensorflow/lite/delegates/gpu/common/tasks/concat_xy.h"
25 #include "tensorflow/lite/delegates/gpu/common/tasks/concat_z.h"
26 #include "tensorflow/lite/delegates/gpu/common/tasks/depthwise_conv.h"
27 #include "tensorflow/lite/delegates/gpu/common/tasks/lstm.h"
28 #include "tensorflow/lite/delegates/gpu/common/tasks/max_unpooling.h"
29 #include "tensorflow/lite/delegates/gpu/common/tasks/padding.h"
30 #include "tensorflow/lite/delegates/gpu/common/tasks/pooling.h"
31 #include "tensorflow/lite/delegates/gpu/common/tasks/prelu.h"
32 #include "tensorflow/lite/delegates/gpu/common/tasks/quantize_and_dequantize.h"
33 #include "tensorflow/lite/delegates/gpu/common/tasks/reduce.h"
34 #include "tensorflow/lite/delegates/gpu/common/tasks/relu.h"
35 #include "tensorflow/lite/delegates/gpu/common/tasks/reshape.h"
36 #include "tensorflow/lite/delegates/gpu/common/tasks/reshapex4.h"
37 #include "tensorflow/lite/delegates/gpu/common/tasks/resize.h"
38 #include "tensorflow/lite/delegates/gpu/common/tasks/softmax.h"
39 #include "tensorflow/lite/delegates/gpu/common/tasks/softmax1x1.h"
40 #include "tensorflow/lite/delegates/gpu/common/tasks/space_to_depth.h"
41 #include "tensorflow/lite/delegates/gpu/common/tasks/split.h"
42 #include "tensorflow/lite/delegates/gpu/common/tasks/strided_slice.h"
43 #include "tensorflow/lite/delegates/gpu/common/tasks/transpose.h"
44 #include "tensorflow/lite/delegates/gpu/common/tasks/winograd.h"
45 
46 namespace tflite {
47 namespace gpu {
48 
SelectLSTM(const OperationDef & op_def,const GpuInfo & gpu_info)49 std::unique_ptr<GPUOperation> SelectLSTM(const OperationDef& op_def,
50                                          const GpuInfo& gpu_info) {
51   return absl::make_unique<GPUOperation>(CreateLSTM(op_def, gpu_info));
52 }
53 
SelectReLU(const ReLUAttributes & attr,const OperationDef & op_def)54 std::unique_ptr<GPUOperation> SelectReLU(const ReLUAttributes& attr,
55                                          const OperationDef& op_def) {
56   return absl::make_unique<GPUOperation>(CreateReLU(op_def, attr));
57 }
58 
SelectPReLU(const PReLUAttributes & attr,const GpuInfo & gpu_info,const OperationDef & op_def)59 std::unique_ptr<GPUOperation> SelectPReLU(const PReLUAttributes& attr,
60                                           const GpuInfo& gpu_info,
61                                           const OperationDef& op_def) {
62   return absl::make_unique<GPUOperation>(CreatePReLU(gpu_info, op_def, attr));
63 }
64 
SelectPooling(const Pooling2DAttributes & attr,const OperationDef & op_def)65 std::unique_ptr<GPUOperation> SelectPooling(const Pooling2DAttributes& attr,
66                                             const OperationDef& op_def) {
67   return absl::make_unique<GPUOperation>(CreatePooling(op_def, attr));
68 }
69 
SelectMaxUnpooling(const MaxUnpooling2DAttributes & attr,const OperationDef & op_def)70 std::unique_ptr<GPUOperation> SelectMaxUnpooling(
71     const MaxUnpooling2DAttributes& attr, const OperationDef& op_def) {
72   return absl::make_unique<GPUOperation>(CreateMaxUnpooling(op_def, attr));
73 }
74 
SelectAdd(const OperationDef & op_def,const std::vector<int> & channels,int dst_channels,std::unique_ptr<GPUOperation> * ptr)75 void SelectAdd(const OperationDef& op_def, const std::vector<int>& channels,
76                int dst_channels, std::unique_ptr<GPUOperation>* ptr) {
77   GPUOperation operation = CreateAdd(op_def, channels, dst_channels);
78   *ptr = absl::make_unique<GPUOperation>(std::move(operation));
79 }
80 
SelectResize(const Resize2DAttributes & attr,const OperationDef & op_def,std::unique_ptr<GPUOperation> * ptr)81 absl::Status SelectResize(const Resize2DAttributes& attr,
82                           const OperationDef& op_def,
83                           std::unique_ptr<GPUOperation>* ptr) {
84   Resize operation = CreateResize(op_def, attr);
85   *ptr = absl::make_unique<Resize>(std::move(operation));
86   return absl::OkStatus();
87 }
88 
SelectConcat(const ConcatAttributes & attr,const std::vector<int> & channels,const OperationDef & op_def,const GpuInfo & gpu_info,std::unique_ptr<GPUOperation> * ptr)89 absl::Status SelectConcat(const ConcatAttributes& attr,
90                           const std::vector<int>& channels,
91                           const OperationDef& op_def, const GpuInfo& gpu_info,
92                           std::unique_ptr<GPUOperation>* ptr) {
93   switch (attr.axis) {
94     case Axis::CHANNELS: {
95       GPUOperation operation = CreateConcatZ(op_def, channels, gpu_info);
96       *ptr = absl::make_unique<GPUOperation>(std::move(operation));
97       return absl::OkStatus();
98     }
99     case Axis::BATCH:
100     case Axis::DEPTH:
101     case Axis::HEIGHT:
102     case Axis::WIDTH: {
103       GPUOperation operation = CreateConcatXY(op_def, attr);
104       *ptr = absl::make_unique<GPUOperation>(std::move(operation));
105       return absl::OkStatus();
106     }
107     default:
108       return absl::UnimplementedError("No concat for this axis.");
109   }
110 }
111 
SelectDWConvolutionDynamicWeights(const DepthwiseConvolution2DAttributes & attr,const GpuInfo & gpu_info,const OperationDef & op_def)112 std::unique_ptr<GPUOperation> SelectDWConvolutionDynamicWeights(
113     const DepthwiseConvolution2DAttributes& attr, const GpuInfo& gpu_info,
114     const OperationDef& op_def) {
115   return absl::make_unique<GPUOperation>(
116       CreateDepthwiseConvolution2DDynamicWeights(gpu_info, op_def, attr));
117 }
118 
SelectReshape(int src_channels,int dst_channels,const OperationDef & op_def,std::unique_ptr<GPUOperation> * ptr)119 void SelectReshape(int src_channels, int dst_channels,
120                    const OperationDef& op_def,
121                    std::unique_ptr<GPUOperation>* ptr) {
122   if (src_channels % 4 == 0 && dst_channels % 4 == 0) {
123     GPUOperation operation = CreateReshapex4(op_def);
124     *ptr = absl::make_unique<GPUOperation>(std::move(operation));
125   } else {
126     GPUOperation operation = CreateReshape(op_def);
127     *ptr = absl::make_unique<GPUOperation>(std::move(operation));
128   }
129 }
130 
SelectSpaceToDepth(const SpaceToDepthAttributes & attr,const OperationDef & op_def,std::unique_ptr<GPUOperation> * ptr)131 void SelectSpaceToDepth(const SpaceToDepthAttributes& attr,
132                         const OperationDef& op_def,
133                         std::unique_ptr<GPUOperation>* ptr) {
134   GPUOperation operation = CreateSpaceToDepth(op_def, attr);
135   *ptr = absl::make_unique<GPUOperation>(std::move(operation));
136 }
137 
SelectSplit(const SplitAttributes & attr,const OperationDef & op_def,std::unique_ptr<GPUOperation> * ptr)138 absl::Status SelectSplit(const SplitAttributes& attr,
139                          const OperationDef& op_def,
140                          std::unique_ptr<GPUOperation>* ptr) {
141   if (attr.axis != Axis::CHANNELS) {
142     return absl::UnimplementedError("No split for this axis.");
143   }
144   Split operation = CreateSplit(op_def, attr);
145   *ptr = absl::make_unique<Split>(std::move(operation));
146   return absl::OkStatus();
147 }
148 
SelectPadding(const PadAttributes & attr,const OperationDef & op_def,std::unique_ptr<GPUOperation> * ptr)149 void SelectPadding(const PadAttributes& attr, const OperationDef& op_def,
150                    std::unique_ptr<GPUOperation>* ptr) {
151   GPUOperation operation = CreatePadding(op_def, attr);
152   *ptr = absl::make_unique<GPUOperation>(std::move(operation));
153 }
154 
SelectStridedSlice(const SliceAttributes & attr,const OperationDef & op_def,std::unique_ptr<GPUOperation> * ptr)155 void SelectStridedSlice(const SliceAttributes& attr, const OperationDef& op_def,
156                         std::unique_ptr<GPUOperation>* ptr) {
157   StridedSlice operation = CreateStridedSlice(op_def, attr);
158   *ptr = absl::make_unique<StridedSlice>(std::move(operation));
159 }
160 
SelectReduce(const std::set<Axis> & axis_to_reduce,const BHWC & src_shape,OperationType op_type,const OperationDef & op_def,const GpuInfo & gpu_info)161 std::unique_ptr<GPUOperation> SelectReduce(const std::set<Axis>& axis_to_reduce,
162                                            const BHWC& src_shape,
163                                            OperationType op_type,
164                                            const OperationDef& op_def,
165                                            const GpuInfo& gpu_info) {
166   return absl::make_unique<Reduce>(
167       CreateReduce(axis_to_reduce, src_shape, op_type, op_def, gpu_info));
168 }
169 
SelectSoftmax(const BHWC & shape,const OperationDef & op_def,std::unique_ptr<GPUOperation> * ptr)170 void SelectSoftmax(const BHWC& shape, const OperationDef& op_def,
171                    std::unique_ptr<GPUOperation>* ptr) {
172   if (shape.w == 1 && shape.h == 1) {
173     Softmax1x1 operation = CreateSoftmax1x1(op_def);
174     *ptr = absl::make_unique<Softmax1x1>(std::move(operation));
175   } else {
176     GPUOperation operation = CreateSoftmax(op_def);
177     *ptr = absl::make_unique<GPUOperation>(std::move(operation));
178   }
179 }
180 
SelectTranspose(const TransposeAttributes & attr,const OperationDef & op_def,std::unique_ptr<GPUOperation> * ptr)181 void SelectTranspose(const TransposeAttributes& attr,
182                      const OperationDef& op_def,
183                      std::unique_ptr<GPUOperation>* ptr) {
184   GPUOperation operation = CreateTranspose(op_def, attr);
185   *ptr = absl::make_unique<GPUOperation>(std::move(operation));
186 }
187 
SelectWinograd4x4To36(const GpuInfo & gpu_info,const Padding2D & padding,const OperationDef & op_def)188 std::unique_ptr<GPUOperation> SelectWinograd4x4To36(
189     const GpuInfo& gpu_info, const Padding2D& padding,
190     const OperationDef& op_def) {
191   if (gpu_info.IsApple()) {
192     const auto src_storage = op_def.src_tensors[0].storage_type;
193     const auto dst_storage = op_def.src_tensors[0].storage_type;
194     if ((src_storage == TensorStorageType::BUFFER ||
195          src_storage == TensorStorageType::IMAGE_BUFFER) &&
196         (dst_storage == TensorStorageType::BUFFER ||
197          dst_storage == TensorStorageType::IMAGE_BUFFER)) {
198       Winograd4x4To36 operation = CreateWinograd4x4To36(op_def, padding);
199       return absl::make_unique<Winograd4x4To36>(std::move(operation));
200     }
201   }
202   return absl::make_unique<Winograd4x4To36TileX6>(
203       CreateWinograd4x4To36TileX6(gpu_info, op_def, padding));
204 }
205 
SelectWinograd36To4x4(const GpuInfo & gpu_info,const OperationDef & op_def,const tflite::gpu::Tensor<Linear,DataType::FLOAT32> & biases)206 std::unique_ptr<GPUOperation> SelectWinograd36To4x4(
207     const GpuInfo& gpu_info, const OperationDef& op_def,
208     const tflite::gpu::Tensor<Linear, DataType::FLOAT32>& biases) {
209   if (gpu_info.IsApple()) {
210     const auto src_storage = op_def.src_tensors[0].storage_type;
211     const auto dst_storage = op_def.src_tensors[0].storage_type;
212     if ((src_storage == TensorStorageType::BUFFER ||
213          src_storage == TensorStorageType::IMAGE_BUFFER) &&
214         (dst_storage == TensorStorageType::BUFFER ||
215          dst_storage == TensorStorageType::IMAGE_BUFFER)) {
216       Winograd36To4x4 operation = CreateWinograd36To4x4(op_def, biases);
217       return absl::make_unique<Winograd36To4x4>(std::move(operation));
218     }
219   }
220   return absl::make_unique<Winograd36To4x4Tile4x1>(
221       CreateWinograd36To4x4Tile4x1(gpu_info, op_def, biases));
222 }
223 
SelectQuantizeAndDequantize(const QuantizeAndDequantizeAttributes & attr,const OperationDef & op_def)224 std::unique_ptr<GPUOperation> SelectQuantizeAndDequantize(
225     const QuantizeAndDequantizeAttributes& attr, const OperationDef& op_def) {
226   return absl::make_unique<GPUOperation>(
227       CreateQuantizeAndDequantize(op_def, attr));
228 }
229 
230 }  // namespace gpu
231 }  // namespace tflite
232