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