1 /* Copyright 2019 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 <memory>
17 #include <utility>
18
19 #include "tensorflow/lite/delegates/gpu/common/model_hints.h"
20 #include "tensorflow/lite/delegates/gpu/common/operations.h"
21 #include "tensorflow/lite/delegates/gpu/common/shape.h"
22 #include "tensorflow/lite/delegates/gpu/common/status.h"
23 #include "tensorflow/lite/delegates/gpu/common/task/gpu_operation.h"
24 #include "tensorflow/lite/delegates/gpu/common/task/tensor_desc.h"
25 #include "tensorflow/lite/delegates/gpu/common/task/weights_layout.h"
26 #include "tensorflow/lite/delegates/gpu/common/tasks/conv_constants.h"
27 #include "tensorflow/lite/delegates/gpu/common/tasks/conv_generic.h"
28 #include "tensorflow/lite/delegates/gpu/common/tasks/conv_metal_simd.h"
29 #include "tensorflow/lite/delegates/gpu/common/tasks/conv_weights_converter.h"
30
31 namespace tflite {
32 namespace gpu {
33 namespace {
34
SelectConvolutionAdreno(const Convolution2DAttributes & attr,const BHWC & dst_shape,const GpuInfo & gpu_info,const OperationDef & op_def,ModelHints hints)35 std::unique_ptr<GPUOperation> SelectConvolutionAdreno(
36 const Convolution2DAttributes& attr, const BHWC& dst_shape,
37 const GpuInfo& gpu_info, const OperationDef& op_def,
38 ModelHints hints) {
39 if (IsConvConstantsSupported(gpu_info, op_def, attr)) {
40 GPUOperation conv = CreateConvConstants(gpu_info, op_def, attr);
41 return std::make_unique<GPUOperation>(std::move(conv));
42 } else {
43 ConvGeneric conv = CreateConvGeneric(gpu_info, op_def, attr, &dst_shape);
44 return std::make_unique<ConvGeneric>(std::move(conv));
45 }
46 }
47
SelectConvolutionNVidia(const Convolution2DAttributes & attr,const BHWC & dst_shape,const GpuInfo & gpu_info,const OperationDef & op_def)48 std::unique_ptr<GPUOperation> SelectConvolutionNVidia(
49 const Convolution2DAttributes& attr, const BHWC& dst_shape,
50 const GpuInfo& gpu_info, const OperationDef& op_def) {
51 if (IsConvConstantsSupported(gpu_info, op_def, attr)) {
52 GPUOperation conv = CreateConvConstants(gpu_info, op_def, attr);
53 return std::make_unique<GPUOperation>(std::move(conv));
54 } else {
55 ConvGeneric conv = CreateConvGeneric(gpu_info, op_def, attr, &dst_shape);
56 return std::make_unique<ConvGeneric>(std::move(conv));
57 }
58 }
59
SelectConvolutionApple(const Convolution2DAttributes & attr,const BHWC & dst_shape,const GpuInfo & gpu_info,const OperationDef & op_def)60 std::unique_ptr<GPUOperation> SelectConvolutionApple(
61 const Convolution2DAttributes& attr, const BHWC& dst_shape,
62 const GpuInfo& gpu_info, const OperationDef& op_def) {
63 if (IsConvolutionMetalSimdSupported(gpu_info, op_def, attr) &&
64 op_def.precision == CalculationsPrecision::F32 && gpu_info.IsApple() &&
65 gpu_info.apple_info.IsSIMDMatMulFp32Perf2x() &&
66 IsGoodTaskSizeForAppleConvSimd(dst_shape, gpu_info)) {
67 ConvolutionMetalSimd conv =
68 CreateConvolutionMetalSimd(op_def, dst_shape, attr, gpu_info);
69 return std::make_unique<ConvolutionMetalSimd>(std::move(conv));
70 } else {
71 ConvGeneric conv = CreateConvGeneric(gpu_info, op_def, attr, &dst_shape);
72 return std::make_unique<ConvGeneric>(std::move(conv));
73 }
74 }
75
76 } // namespace
77
SelectConvolution(const Convolution2DAttributes & attr,const BHWC & dst_shape,const GpuInfo & gpu_info,const OperationDef & op_def,ModelHints hints)78 std::unique_ptr<GPUOperation> SelectConvolution(
79 const Convolution2DAttributes& attr, const BHWC& dst_shape,
80 const GpuInfo& gpu_info, const OperationDef& op_def,
81 ModelHints hints) {
82 if (gpu_info.IsApple()) {
83 return SelectConvolutionApple(attr, dst_shape, gpu_info, op_def);
84 } else if (gpu_info.IsAdreno()) {
85 return SelectConvolutionAdreno(attr, dst_shape, gpu_info, op_def, hints);
86 } else if (gpu_info.IsPowerVR() || gpu_info.IsAMD() || gpu_info.IsIntel() ||
87 gpu_info.IsApple() || gpu_info.IsMali()) {
88 ConvGeneric conv = CreateConvGeneric(gpu_info, op_def, attr, &dst_shape);
89 return std::make_unique<ConvGeneric>(std::move(conv));
90 } else if (gpu_info.IsNvidia()) {
91 return SelectConvolutionNVidia(attr, dst_shape, gpu_info, op_def);
92 } else {
93 return SelectConvolutionAdreno(attr, dst_shape, gpu_info, op_def, hints);
94 }
95 }
96
SelectConvolutionForWinograd(const Convolution2DAttributes & attr,const BHWC & dst_shape,const GpuInfo & gpu_info,const OperationDef & op_def,ModelHints hints)97 std::unique_ptr<GPUOperation> SelectConvolutionForWinograd(
98 const Convolution2DAttributes& attr, const BHWC& dst_shape,
99 const GpuInfo& gpu_info, const OperationDef& op_def,
100 ModelHints hints) {
101 ConvGeneric conv =
102 CreateConvGenericWino4x4To6x6(gpu_info, op_def, attr, &dst_shape);
103 return std::make_unique<ConvGeneric>(std::move(conv));
104 }
105
SelectConvolutionWithDynamicWeights(const Convolution2DAttributes & attr,const BHWC & weights_shape,const BHWC & dst_shape,const GpuInfo & gpu_info,const OperationDef & op_def,ModelHints hints,WeightsDescription * weights_desc)106 std::unique_ptr<GPUOperation> SelectConvolutionWithDynamicWeights(
107 const Convolution2DAttributes& attr, const BHWC& weights_shape,
108 const BHWC& dst_shape, const GpuInfo& gpu_info,
109 const OperationDef& op_def, ModelHints hints,
110 WeightsDescription* weights_desc) {
111 ConvGeneric conv = CreateConvGenericDynamicWeights(
112 gpu_info, op_def, attr, weights_shape, &dst_shape);
113 *weights_desc = conv.GetWeightsDescription();
114 return std::make_unique<ConvGeneric>(std::move(conv));
115 }
116
SelectConvolutionBatchedMatMul(const OHWI & weights_shape,const BHWC & dst_shape,const GpuInfo & gpu_info,const OperationDef & op_def,ModelHints hints,WeightsDescription * weights_desc)117 std::unique_ptr<GPUOperation> SelectConvolutionBatchedMatMul(
118 const OHWI& weights_shape, const BHWC& dst_shape, const GpuInfo& gpu_info,
119 const OperationDef& op_def, ModelHints hints,
120 WeightsDescription* weights_desc) {
121 ConvGeneric conv = CreateConvGenericBatchedMatMul(
122 gpu_info, op_def, weights_shape, &dst_shape);
123 *weights_desc = conv.GetWeightsDescription();
124 return std::make_unique<ConvGeneric>(std::move(conv));
125 }
126
SelectConverterToConvWeights(const WeightsDescription & weights_desc,const OperationDef & op_def,ModelHints hints,Layout input_layout)127 std::unique_ptr<GPUOperation> SelectConverterToConvWeights(
128 const WeightsDescription& weights_desc, const OperationDef& op_def,
129 ModelHints hints, Layout input_layout) {
130 ConverterToConvWeights converter =
131 ConverterToConvWeights(op_def, weights_desc, input_layout);
132 return std::make_unique<ConverterToConvWeights>(std::move(converter));
133 }
134
135 } // namespace gpu
136 } // namespace tflite
137