xref: /aosp_15_r20/external/tensorflow/tensorflow/lite/delegates/gpu/common/tasks/reduce_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/reduce_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/reduce.h"
25 
26 namespace tflite {
27 namespace gpu {
28 namespace {
29 template <DataType T>
ReduceSumChannelsIntTest(TestExecutionEnvironment * env)30 absl::Status ReduceSumChannelsIntTest(TestExecutionEnvironment* env) {
31   tflite::gpu::Tensor<BHWC, T> src;
32   src.shape = BHWC(1, 2, 1, 5);
33   src.data = {1, 2, -5, -2, 1, 3, 4, -2, 1, 4};
34 
35   const std::set<tflite::gpu::Axis> axis{Axis::CHANNELS};
36 
37   tflite::gpu::Tensor<BHWC, T> ref_tensor;
38   ref_tensor.shape = BHWC(1, 2, 1, 1);
39   ref_tensor.data = {-3, 10};
40 
41   for (auto storage : env->GetSupportedStorages(T)) {
42     OperationDef op_def;
43     op_def.precision = CalculationsPrecision::F32;
44     op_def.src_tensors.push_back({T, storage, Layout::HWC});
45     op_def.dst_tensors.push_back({T, storage, Layout::HWC});
46     TensorDescriptor src_0, dst;
47     src_0 = op_def.src_tensors[0];
48     src_0.UploadData(src);
49     dst.SetBHWCShape(BHWC(1, 2, 1, 1));
50     Reduce operation = CreateReduce(axis, src.shape, OperationType::REDUCE_SUM,
51                                     op_def, env->GetGpuInfo());
52     RETURN_IF_ERROR(env->ExecuteGPUOperation(
53         {&src_0}, {&dst}, std::make_unique<Reduce>(std::move(operation))));
54     tflite::gpu::Tensor<BHWC, T> dst_tensor;
55     dst.DownloadData(&dst_tensor);
56     if (dst_tensor.data != ref_tensor.data) {
57       return absl::InternalError("not equal");
58     }
59   }
60   return absl::OkStatus();
61 }
62 
63 template absl::Status ReduceSumChannelsIntTest<DataType::INT32>(
64     TestExecutionEnvironment* env);
65 template absl::Status ReduceSumChannelsIntTest<DataType::INT16>(
66     TestExecutionEnvironment* env);
67 template absl::Status ReduceSumChannelsIntTest<DataType::INT8>(
68     TestExecutionEnvironment* env);
69 
70 template <DataType T>
ReduceProductChannelsUIntTest(TestExecutionEnvironment * env)71 absl::Status ReduceProductChannelsUIntTest(TestExecutionEnvironment* env) {
72   tflite::gpu::Tensor<BHWC, T> src;
73   src.shape = BHWC(1, 3, 1, 2);
74   src.data = {1, 2, 3, 4, 0, 7};
75   const std::set<tflite::gpu::Axis> axis{Axis::CHANNELS};
76 
77   tflite::gpu::Tensor<BHWC, T> ref_tensor;
78   ref_tensor.shape = BHWC(1, 3, 1, 1);
79   ref_tensor.data = {2, 12, 0};
80 
81   for (auto storage : env->GetSupportedStorages(T)) {
82     OperationDef op_def;
83     op_def.precision = CalculationsPrecision::F32;
84     op_def.src_tensors.push_back({T, storage, Layout::HWC});
85     op_def.dst_tensors.push_back({T, storage, Layout::HWC});
86     TensorDescriptor src_0, dst;
87     src_0 = op_def.src_tensors[0];
88     src_0.UploadData(src);
89     dst.SetBHWCShape(BHWC(1, 3, 1, 1));
90     Reduce operation =
91         CreateReduce(axis, src.shape, OperationType::REDUCE_PRODUCT, op_def,
92                      env->GetGpuInfo());
93     RETURN_IF_ERROR(env->ExecuteGPUOperation(
94         {&src_0}, {&dst}, std::make_unique<Reduce>(std::move(operation))));
95     tflite::gpu::Tensor<BHWC, T> dst_tensor;
96     dst.DownloadData(&dst_tensor);
97     if (dst_tensor.data != ref_tensor.data) {
98       return absl::InternalError("not equal");
99     }
100   }
101   return absl::OkStatus();
102 }
103 
104 template absl::Status ReduceProductChannelsUIntTest<DataType::INT32>(
105     TestExecutionEnvironment* env);
106 template absl::Status ReduceProductChannelsUIntTest<DataType::INT16>(
107     TestExecutionEnvironment* env);
108 template absl::Status ReduceProductChannelsUIntTest<DataType::INT8>(
109     TestExecutionEnvironment* env);
110 }  // namespace
111 
MeanHWTest(TestExecutionEnvironment * env)112 absl::Status MeanHWTest(TestExecutionEnvironment* env) {
113   TensorFloat32 src_tensor;
114   src_tensor.shape = BHWC(1, 2, 2, 1);
115   src_tensor.data = {1.0f, 2.0f, 3.0f, 4.0f};
116   const std::set<tflite::gpu::Axis> axis{Axis::HEIGHT, Axis::WIDTH};
117 
118   for (auto precision : env->GetSupportedPrecisions()) {
119     auto data_type = DeduceDataTypeFromPrecision(precision);
120     for (auto storage : env->GetSupportedStorages(data_type)) {
121       const float eps = precision == CalculationsPrecision::F32 ? 1e-6f : 1e-2f;
122       OperationDef op_def;
123       op_def.precision = precision;
124       op_def.src_tensors.push_back({data_type, storage, Layout::HWC});
125       op_def.dst_tensors.push_back({data_type, storage, Layout::HWC});
126       TensorFloat32 dst_tensor;
127       Reduce operation =
128           CreateReduce(axis, src_tensor.shape, OperationType::MEAN, op_def,
129                        env->GetGpuInfo());
130       RETURN_IF_ERROR(env->ExecuteGPUOperation(
131           src_tensor, std::make_unique<Reduce>(std::move(operation)),
132           BHWC(1, 1, 1, 1), &dst_tensor));
133       RETURN_IF_ERROR(PointWiseNear({2.5f}, dst_tensor.data, eps));
134     }
135   }
136   return absl::OkStatus();
137 }
138 
ReduceSumChannelsTest(TestExecutionEnvironment * env)139 absl::Status ReduceSumChannelsTest(TestExecutionEnvironment* env) {
140   TensorFloat32 src_tensor;
141   src_tensor.shape = BHWC(1, 2, 1, 5);
142   src_tensor.data = {1.1, 2.1, 0.7, 0.3, 1.2, 3.1, 4.1, 0.0, 1.0, 4.4};
143   const std::set<tflite::gpu::Axis> axis{Axis::CHANNELS};
144 
145   for (auto precision : env->GetSupportedPrecisions()) {
146     auto data_type = DeduceDataTypeFromPrecision(precision);
147     for (auto storage : env->GetSupportedStorages(data_type)) {
148       const float eps = precision == CalculationsPrecision::F32 ? 1e-6f : 1e-2f;
149       OperationDef op_def;
150       op_def.precision = precision;
151       op_def.src_tensors.push_back({data_type, storage, Layout::HWC});
152       op_def.dst_tensors.push_back({data_type, storage, Layout::HWC});
153       TensorFloat32 dst_tensor;
154       Reduce operation =
155           CreateReduce(axis, src_tensor.shape, OperationType::REDUCE_SUM,
156                        op_def, env->GetGpuInfo());
157       RETURN_IF_ERROR(env->ExecuteGPUOperation(
158           src_tensor, std::make_unique<Reduce>(std::move(operation)),
159           BHWC(1, 2, 1, 1), &dst_tensor));
160       RETURN_IF_ERROR(PointWiseNear({5.4f, 12.6f}, dst_tensor.data, eps));
161     }
162   }
163 
164   RETURN_IF_ERROR(ReduceSumChannelsIntTest<DataType::INT32>(env));
165   RETURN_IF_ERROR(ReduceSumChannelsIntTest<DataType::INT16>(env));
166   RETURN_IF_ERROR(ReduceSumChannelsIntTest<DataType::INT8>(env));
167   return absl::OkStatus();
168 }
169 
ReduceProductChannelsTest(TestExecutionEnvironment * env)170 absl::Status ReduceProductChannelsTest(TestExecutionEnvironment* env) {
171   TensorFloat32 src_tensor;
172   src_tensor.shape = BHWC(1, 2, 1, 2);
173   src_tensor.data = {1.1, 2.0, 3.1, 4.0};
174   const std::set<tflite::gpu::Axis> axis{Axis::CHANNELS};
175 
176   for (auto precision : env->GetSupportedPrecisions()) {
177     auto data_type = DeduceDataTypeFromPrecision(precision);
178     for (auto storage : env->GetSupportedStorages(data_type)) {
179       const float eps = precision == CalculationsPrecision::F32 ? 1e-6f : 1e-2f;
180       OperationDef op_def;
181       op_def.precision = precision;
182       op_def.src_tensors.push_back({data_type, storage, Layout::HWC});
183       op_def.dst_tensors.push_back({data_type, storage, Layout::HWC});
184       TensorFloat32 dst_tensor;
185       Reduce operation =
186           CreateReduce(axis, src_tensor.shape, OperationType::REDUCE_PRODUCT,
187                        op_def, env->GetGpuInfo());
188       RETURN_IF_ERROR(env->ExecuteGPUOperation(
189           src_tensor, std::make_unique<Reduce>(std::move(operation)),
190           BHWC(1, 2, 1, 1), &dst_tensor));
191       RETURN_IF_ERROR(PointWiseNear({2.2f, 12.4f}, dst_tensor.data, eps));
192     }
193   }
194 
195   RETURN_IF_ERROR(ReduceProductChannelsUIntTest<DataType::UINT32>(env));
196   RETURN_IF_ERROR(ReduceProductChannelsUIntTest<DataType::UINT16>(env));
197   RETURN_IF_ERROR(ReduceProductChannelsUIntTest<DataType::UINT8>(env));
198   return absl::OkStatus();
199 }
200 
ReduceMaxChannelsTest(TestExecutionEnvironment * env)201 absl::Status ReduceMaxChannelsTest(TestExecutionEnvironment* env) {
202   TensorFloat32 src_tensor;
203   src_tensor.shape = BHWC(1, 2, 1, 6);
204   src_tensor.data = {1.1,  2.0,  -0.3, -100.0, 32.6, 1.1,
205                      -3.1, -4.0, -5.0, -7.0,   -2.0, -100.0};
206   const std::set<tflite::gpu::Axis> axis{Axis::CHANNELS};
207 
208   for (auto precision : env->GetSupportedPrecisions()) {
209     auto data_type = DeduceDataTypeFromPrecision(precision);
210     for (auto storage : env->GetSupportedStorages(data_type)) {
211       const float eps = precision == CalculationsPrecision::F32 ? 1e-6f : 1e-2f;
212       OperationDef op_def;
213       op_def.precision = precision;
214       op_def.src_tensors.push_back({data_type, storage, Layout::HWC});
215       op_def.dst_tensors.push_back({data_type, storage, Layout::HWC});
216       TensorFloat32 dst_tensor;
217       Reduce operation =
218           CreateReduce(axis, src_tensor.shape, OperationType::REDUCE_MAXIMUM,
219                        op_def, env->GetGpuInfo());
220       RETURN_IF_ERROR(env->ExecuteGPUOperation(
221           src_tensor, std::make_unique<Reduce>(std::move(operation)),
222           BHWC(1, 2, 1, 1), &dst_tensor));
223       RETURN_IF_ERROR(PointWiseNear({32.6f, -2.0f}, dst_tensor.data, eps));
224     }
225   }
226   return absl::OkStatus();
227 }
228 
ReduceMinChannelsTest(TestExecutionEnvironment * env)229 absl::Status ReduceMinChannelsTest(TestExecutionEnvironment* env) {
230   TensorFloat32 src_tensor;
231   src_tensor.shape = BHWC(1, 2, 1, 6);
232   src_tensor.data = {1.1,  2.0,  -0.3, -100.0, 32.6, 1.1,
233                      -3.1, -4.0, -5.0, -7.0,   -2.0, 100.0};
234   const std::set<tflite::gpu::Axis> axis{Axis::CHANNELS};
235 
236   for (auto precision : env->GetSupportedPrecisions()) {
237     auto data_type = DeduceDataTypeFromPrecision(precision);
238     for (auto storage : env->GetSupportedStorages(data_type)) {
239       const float eps = precision == CalculationsPrecision::F32 ? 1e-6f : 1e-2f;
240       OperationDef op_def;
241       op_def.precision = precision;
242       op_def.src_tensors.push_back({data_type, storage, Layout::HWC});
243       op_def.dst_tensors.push_back({data_type, storage, Layout::HWC});
244       TensorFloat32 dst_tensor;
245       Reduce operation =
246           CreateReduce(axis, src_tensor.shape, OperationType::REDUCE_MINIMUM,
247                        op_def, env->GetGpuInfo());
248       RETURN_IF_ERROR(env->ExecuteGPUOperation(
249           src_tensor, std::make_unique<Reduce>(std::move(operation)),
250           BHWC(1, 2, 1, 1), &dst_tensor));
251       RETURN_IF_ERROR(PointWiseNear({-100.0f, -7.0f}, dst_tensor.data, eps));
252     }
253   }
254   return absl::OkStatus();
255 }
256 
257 }  // namespace gpu
258 }  // namespace tflite
259