xref: /aosp_15_r20/external/tensorflow/tensorflow/lite/delegates/gpu/common/tasks/fully_connected_test_util.cc (revision b6fb3261f9314811a0f4371741dbb8839866f948)
1 /* Copyright 2021 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/tasks/fully_connected_test_util.h"
17 
18 #include <memory>
19 #include <vector>
20 
21 #include "tensorflow/lite/delegates/gpu/common/operations.h"
22 #include "tensorflow/lite/delegates/gpu/common/status.h"
23 #include "tensorflow/lite/delegates/gpu/common/task/testing_util.h"
24 #include "tensorflow/lite/delegates/gpu/common/tasks/fully_connected.h"
25 
26 namespace tflite {
27 namespace gpu {
28 
FullyConnectedTest(TestExecutionEnvironment * env)29 absl::Status FullyConnectedTest(TestExecutionEnvironment* env) {
30   TensorFloat32 src_tensor;
31   src_tensor.shape = BHWC(1, 1, 1, 4);
32   src_tensor.data = {0.0f, 1.0f, 2.0f, 3.0f};
33 
34   FullyConnectedAttributes attr;
35   attr.weights.shape = OHWI(2, 1, 1, 4);
36   attr.weights.data = {0.0f, 1.0f, 2.0f, 3.0f,  //
37                        4.0f, 5.0f, 6.0f, 7.0f};
38   attr.bias.shape = Linear(2);
39   attr.bias.data = {0.5f, -0.5f};
40 
41   for (auto precision : env->GetSupportedPrecisions()) {
42     auto data_type = DeduceDataTypeFromPrecision(precision);
43     for (auto storage : env->GetSupportedStorages(data_type)) {
44       const float eps = precision == CalculationsPrecision::F32 ? 1e-6f : 1e-3f;
45       OperationDef op_def;
46       op_def.precision = precision;
47       op_def.src_tensors.push_back({data_type, storage, Layout::HWC});
48       op_def.dst_tensors.push_back({data_type, storage, Layout::HWC});
49       TensorFloat32 dst_tensor;
50       FullyConnected operation =
51           CreateFullyConnected(env->GetGpuInfo(), op_def, attr);
52       RETURN_IF_ERROR(env->ExecuteGPUOperation(
53           src_tensor, std::make_unique<FullyConnected>(std::move(operation)),
54           BHWC(1, 1, 1, 2), &dst_tensor));
55       RETURN_IF_ERROR(PointWiseNear({14.5f, 37.5f}, dst_tensor.data, eps))
56           << "Failed using precision " << ToString(precision);
57     }
58   }
59   return absl::OkStatus();
60 }
61 
FullyConnectedLargeTest(TestExecutionEnvironment * env)62 absl::Status FullyConnectedLargeTest(TestExecutionEnvironment* env) {
63   TensorFloat32 src_tensor;
64   src_tensor.shape = BHWC(1, 1, 1, 8);
65   src_tensor.data = {0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f};
66 
67   FullyConnectedAttributes attr;
68   attr.weights.shape = OHWI(12, 1, 1, 8);
69   attr.weights.data = {
70       0.0f,  1.0f,  2.0f,  3.0f,  4.0f,  5.0f,  6.0f,  7.0f,   //
71       8.0f,  9.0f,  10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f,  //
72       16.0f, 17.0f, 18.0f, 19.0f, 20.0f, 21.0f, 22.0f, 23.0f,  //
73       24.0f, 25.0f, 26.0f, 27.0f, 28.0f, 29.0f, 30.0f, 31.0f,  //
74       32.0f, 33.0f, 34.0f, 35.0f, 36.0f, 37.0f, 38.0f, 39.0f,  //
75       40.0f, 41.0f, 42.0f, 43.0f, 44.0f, 45.0f, 46.0f, 47.0f,  //
76       48.0f, 49.0f, 50.0f, 51.0f, 52.0f, 53.0f, 54.0f, 55.0f,  //
77       56.0f, 57.0f, 58.0f, 59.0f, 60.0f, 61.0f, 62.0f, 63.0f,  //
78       64.0f, 65.0f, 66.0f, 67.0f, 68.0f, 69.0f, 70.0f, 71.0f,  //
79       72.0f, 73.0f, 74.0f, 75.0f, 76.0f, 77.0f, 78.0f, 79.0f,  //
80       80.0f, 81.0f, 82.0f, 83.0f, 84.0f, 85.0f, 86.0f, 87.0f,  //
81       88.0f, 89.0f, 90.0f, 91.0f, 92.0f, 93.0f, 94.0f, 95.0f,  //
82   };
83   attr.bias.shape = Linear(12);
84   attr.bias.data = {-0.6f, -0.5f, -0.4f, -0.3f, -0.2f, -0.1f,
85                     0.1f,  0.2f,  0.3f,  0.4f,  0.5f,  0.6f};
86 
87   for (auto precision : env->GetSupportedPrecisions()) {
88     auto data_type = DeduceDataTypeFromPrecision(precision);
89     for (auto storage : env->GetSupportedStorages(data_type)) {
90       const float eps = precision == CalculationsPrecision::F32 ? 0.0f : 1.0f;
91       OperationDef op_def;
92       op_def.precision = precision;
93       op_def.src_tensors.push_back({data_type, storage, Layout::HWC});
94       op_def.dst_tensors.push_back({data_type, storage, Layout::HWC});
95       TensorFloat32 dst_tensor;
96       FullyConnected operation =
97           CreateFullyConnected(env->GetGpuInfo(), op_def, attr);
98       RETURN_IF_ERROR(env->ExecuteGPUOperation(
99           src_tensor, std::make_unique<FullyConnected>(std::move(operation)),
100           BHWC(1, 1, 1, 12), &dst_tensor));
101       RETURN_IF_ERROR(
102           PointWiseNear({139.4f, 363.5f, 587.6f, 811.7f, 1035.8f, 1259.9f,
103                          1484.1f, 1708.2f, 1932.3f, 2156.4f, 2380.5f, 2604.6f},
104                         dst_tensor.data, eps))
105           << "Failed using precision " << ToString(precision);
106     }
107   }
108   return absl::OkStatus();
109 }
110 
FullyConnectedExtraLargeTest(TestExecutionEnvironment * env)111 absl::Status FullyConnectedExtraLargeTest(TestExecutionEnvironment* env) {
112   static const int kInputSize = 1024;
113   static const int kOutputSize = 1024;
114   TensorFloat32 src_tensor;
115   src_tensor.shape = BHWC(1, 1, 1, kInputSize);
116   src_tensor.data.assign(kInputSize, 1.1f);
117 
118   FullyConnectedAttributes attr;
119   attr.weights.shape = OHWI(1024, 1, 1, kInputSize);
120   attr.weights.data.assign(kOutputSize * kInputSize, 2.2f);
121   attr.bias.shape = Linear(kOutputSize);
122   attr.bias.data.assign(kOutputSize, 3.3f);
123 
124   std::vector<float> expected(kOutputSize, 2481.38f);
125 
126   for (auto precision : env->GetSupportedPrecisions()) {
127     auto data_type = DeduceDataTypeFromPrecision(precision);
128     for (auto storage : env->GetSupportedStorages(data_type)) {
129       float eps;
130       switch (precision) {
131         case CalculationsPrecision::F32:
132           eps = 2.45e-3f;
133           break;
134         case CalculationsPrecision::F32_F16:
135           eps = 1.38f;
136           break;
137         case CalculationsPrecision::F16:
138           eps = 39.0f;
139           break;
140       }
141       if (precision == CalculationsPrecision::F32_F16 &&
142           env->GetGpuInfo().IsApiMetal() && env->GetGpuInfo().IsIntel()) {
143         eps = 3.5f;
144       }
145       if (precision == CalculationsPrecision::F32_F16 &&
146           env->GetGpuInfo().IsGlsl()) {
147         eps = 3.5f;
148       }
149       if (!env->GetGpuInfo().IsRoundToNearestSupported()) {
150         eps *= 4.0f;
151       }
152       OperationDef op_def;
153       op_def.precision = precision;
154       op_def.src_tensors.push_back({data_type, storage, Layout::HWC});
155       op_def.dst_tensors.push_back({data_type, storage, Layout::HWC});
156       TensorFloat32 dst_tensor;
157       FullyConnected operation =
158           CreateFullyConnected(env->GetGpuInfo(), op_def, attr);
159       RETURN_IF_ERROR(env->ExecuteGPUOperation(
160           src_tensor, std::make_unique<FullyConnected>(std::move(operation)),
161           BHWC(1, 1, 1, kOutputSize), &dst_tensor));
162       RETURN_IF_ERROR(PointWiseNear(expected, dst_tensor.data, eps))
163           << "Failed using precision " << ToString(precision);
164     }
165   }
166   return absl::OkStatus();
167 }
168 
FullyConnectedInt8Test(TestExecutionEnvironment * env)169 absl::Status FullyConnectedInt8Test(TestExecutionEnvironment* env) {
170   TensorFloat32 src_tensor;
171   src_tensor.shape = BHWC(1, 1, 1, 4);
172   src_tensor.data = {0.0f, 1.0f, 2.0f, 3.0f};
173 
174   FullyConnectedInt8Attributes attr;
175   attr.weights.shape = OHWI(2, 1, 1, 4);
176   attr.weights.data = {2,  4,  6,   8,  //
177                        10, 12, -14, 16};
178   attr.bias.shape = Linear(2);
179   attr.bias.data = {0.5f, -0.5f};
180   attr.scale = 0.5f;
181   attr.zero_point = 0;
182 
183   for (auto precision : env->GetSupportedPrecisions()) {
184     auto data_type = DeduceDataTypeFromPrecision(precision);
185     for (auto storage : env->GetSupportedStorages(data_type)) {
186       const float eps = precision == CalculationsPrecision::F32 ? 1e-6f : 1e-3f;
187       OperationDef op_def;
188       op_def.precision = precision;
189       op_def.src_tensors.push_back({data_type, storage, Layout::HWC});
190       op_def.dst_tensors.push_back({data_type, storage, Layout::HWC});
191       TensorFloat32 dst_tensor;
192       FullyConnected operation =
193           CreateFullyConnected(env->GetGpuInfo(), op_def, attr);
194       RETURN_IF_ERROR(env->ExecuteGPUOperation(
195           src_tensor, std::make_unique<FullyConnected>(std::move(operation)),
196           BHWC(1, 1, 1, 2), &dst_tensor));
197       RETURN_IF_ERROR(PointWiseNear({20.5f, 15.5f}, dst_tensor.data, eps))
198           << "Failed using precision " << ToString(precision);
199     }
200   }
201   return absl::OkStatus();
202 }
203 
204 }  // namespace gpu
205 }  // namespace tflite
206