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