xref: /aosp_15_r20/external/tensorflow/tensorflow/lite/delegates/gpu/common/task/testing_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/task/testing_util.h"
17 
18 #include <memory>
19 #include <utility>
20 #include <vector>
21 
22 #include "absl/strings/str_cat.h"
23 
24 namespace tflite {
25 namespace gpu {
26 
ExecuteGPUOperation(const std::vector<TensorDescriptor * > & src_cpu,const std::vector<TensorDescriptor * > & dst_cpu,std::unique_ptr<GPUOperation> && operation)27 absl::Status TestExecutionEnvironment::ExecuteGPUOperation(
28     const std::vector<TensorDescriptor*>& src_cpu,
29     const std::vector<TensorDescriptor*>& dst_cpu,
30     std::unique_ptr<GPUOperation>&& operation) {
31   const OperationDef& op_def = operation->GetDefinition();
32   for (int i = 0; i < src_cpu.size(); ++i) {
33     auto src_shape = src_cpu[i]->GetBHWDCShape();
34     if (src_shape.b != 1 && !op_def.IsBatchSupported()) {
35       return absl::InvalidArgumentError(
36           "Layout doesn't have Batch dimension, but shape.b != 1");
37     }
38   }
39 
40   for (int i = 0; i < dst_cpu.size(); ++i) {
41     auto dst_shape = dst_cpu[i]->GetBHWDCShape();
42     if (dst_shape.b != 1 && !op_def.IsBatchSupported()) {
43       return absl::InvalidArgumentError(
44           "Layout doesn't have Batch dimension, but shape.b != 1");
45     }
46   }
47   RETURN_IF_ERROR(operation->AssembleCode(GetGpuInfo()));
48   return ExecuteGpuOperationInternal(src_cpu, dst_cpu, std::move(operation));
49 }
50 
ExecuteGPUOperation(const std::vector<TensorFloat32> & src_cpu,std::unique_ptr<GPUOperation> && operation,const std::vector<BHWC> & dst_sizes,const std::vector<TensorFloat32 * > & dst_cpu)51 absl::Status TestExecutionEnvironment::ExecuteGPUOperation(
52     const std::vector<TensorFloat32>& src_cpu,
53     std::unique_ptr<GPUOperation>&& operation,
54     const std::vector<BHWC>& dst_sizes,
55     const std::vector<TensorFloat32*>& dst_cpu) {
56   const OperationDef& op_def = operation->GetDefinition();
57   std::vector<TensorDescriptor> src_cpu_descs(src_cpu.size());
58   std::vector<TensorDescriptor*> src_cpu_desc_ptrs(src_cpu.size());
59   for (int i = 0; i < src_cpu.size(); ++i) {
60     src_cpu_descs[i] = op_def.src_tensors[i];
61     src_cpu_descs[i].UploadData(src_cpu[i]);
62     src_cpu_desc_ptrs[i] = &src_cpu_descs[i];
63   }
64   std::vector<TensorDescriptor> dst_cpu_descs(dst_cpu.size());
65   std::vector<TensorDescriptor*> dst_cpu_desc_ptrs(dst_cpu.size());
66   for (int i = 0; i < dst_cpu.size(); ++i) {
67     dst_cpu_descs[i] = op_def.dst_tensors[i];
68     dst_cpu_descs[i].SetBHWCShape(dst_sizes[i]);
69     dst_cpu_desc_ptrs[i] = &dst_cpu_descs[i];
70   }
71 
72   RETURN_IF_ERROR(ExecuteGPUOperation(src_cpu_desc_ptrs, dst_cpu_desc_ptrs,
73                                       std::move(operation)));
74 
75   for (int i = 0; i < dst_cpu.size(); ++i) {
76     dst_cpu_descs[i].DownloadData(dst_cpu[i]);
77   }
78   return absl::OkStatus();
79 }
80 
ExecuteGPUOperation(const std::vector<Tensor5DFloat32> & src_cpu,std::unique_ptr<GPUOperation> && operation,const std::vector<BHWDC> & dst_sizes,const std::vector<Tensor5DFloat32 * > & dst_cpu)81 absl::Status TestExecutionEnvironment::ExecuteGPUOperation(
82     const std::vector<Tensor5DFloat32>& src_cpu,
83     std::unique_ptr<GPUOperation>&& operation,
84     const std::vector<BHWDC>& dst_sizes,
85     const std::vector<Tensor5DFloat32*>& dst_cpu) {
86   const OperationDef& op_def = operation->GetDefinition();
87   std::vector<TensorDescriptor> src_cpu_descs(src_cpu.size());
88   std::vector<TensorDescriptor*> src_cpu_desc_ptrs(src_cpu.size());
89   for (int i = 0; i < src_cpu.size(); ++i) {
90     src_cpu_descs[i] = op_def.src_tensors[i];
91     src_cpu_descs[i].UploadData(src_cpu[i]);
92     src_cpu_desc_ptrs[i] = &src_cpu_descs[i];
93   }
94   std::vector<TensorDescriptor> dst_cpu_descs(dst_cpu.size());
95   std::vector<TensorDescriptor*> dst_cpu_desc_ptrs(dst_cpu.size());
96   for (int i = 0; i < dst_cpu.size(); ++i) {
97     dst_cpu_descs[i] = op_def.dst_tensors[i];
98     dst_cpu_descs[i].SetBHWDCShape(dst_sizes[i]);
99     dst_cpu_desc_ptrs[i] = &dst_cpu_descs[i];
100   }
101 
102   RETURN_IF_ERROR(ExecuteGPUOperation(src_cpu_desc_ptrs, dst_cpu_desc_ptrs,
103                                       std::move(operation)));
104 
105   for (int i = 0; i < dst_cpu.size(); ++i) {
106     dst_cpu_descs[i].DownloadData(dst_cpu[i]);
107   }
108   return absl::OkStatus();
109 }
110 
PointWiseNear(const std::vector<float> & ref,const std::vector<float> & to_compare,float eps)111 absl::Status PointWiseNear(const std::vector<float>& ref,
112                            const std::vector<float>& to_compare, float eps) {
113   if (ref.size() != to_compare.size()) {
114     return absl::InternalError(absl::StrCat("ref size(", ref.size(),
115                                             ") != to_compare size(",
116                                             to_compare.size(), ")"));
117   }
118   for (int i = 0; i < ref.size(); ++i) {
119     const float abs_diff = fabs(ref[i] - to_compare[i]);
120     if (abs_diff > eps) {
121       return absl::InternalError(absl::StrCat(
122           "ref[", i, "] = ", ref[i], ", to_compare[", i, "] = ", to_compare[i],
123           ", abs diff = ", abs_diff, " > ", eps, " (eps)"));
124     }
125   }
126   return absl::OkStatus();
127 }
128 
ExecuteGpuModel(const std::vector<TensorFloat32> & src_cpu,const std::vector<TensorFloat32 * > & dst_cpu,GpuModel * gpu_model)129 absl::Status TestExecutionEnvironment::ExecuteGpuModel(
130     const std::vector<TensorFloat32>& src_cpu,
131     const std::vector<TensorFloat32*>& dst_cpu, GpuModel* gpu_model) {
132   std::vector<TensorFloat32> inputs = src_cpu;
133   for (int k = 0; k < gpu_model->nodes.size(); ++k) {
134     auto& gpu_node = gpu_model->nodes[k];
135     std::vector<TensorDescriptor> src_cpu_descs(gpu_node.inputs.size());
136     std::vector<TensorDescriptor*> src_cpu_desc_ptrs(gpu_node.inputs.size());
137     for (int i = 0; i < gpu_node.inputs.size(); ++i) {
138       src_cpu_descs[i] = gpu_model->tensors[gpu_node.inputs[i]];
139       src_cpu_descs[i].UploadData(inputs[i]);
140       src_cpu_desc_ptrs[i] = &src_cpu_descs[i];
141     }
142 
143     std::vector<TensorDescriptor> dst_cpu_descs(gpu_node.outputs.size());
144     std::vector<TensorDescriptor*> dst_cpu_desc_ptrs(gpu_node.outputs.size());
145     for (int i = 0; i < gpu_node.outputs.size(); ++i) {
146       dst_cpu_descs[i] = gpu_model->tensors[gpu_node.outputs[i]];
147       dst_cpu_desc_ptrs[i] = &dst_cpu_descs[i];
148     }
149 
150     RETURN_IF_ERROR(ExecuteGpuOperationInternal(
151         src_cpu_desc_ptrs, dst_cpu_desc_ptrs,
152         std::move(gpu_model->nodes[k].gpu_operation)));
153 
154     inputs.resize(gpu_node.outputs.size());
155     for (int i = 0; i < gpu_node.outputs.size(); ++i) {
156       dst_cpu_descs[i].DownloadData(&inputs[i]);
157     }
158   }
159   if (dst_cpu.size() != inputs.size()) {
160     return absl::InternalError("Size mismatch.");
161   }
162   for (int i = 0; i < dst_cpu.size(); ++i) {
163     *dst_cpu[i] = inputs[i];
164   }
165   return absl::OkStatus();
166 }
167 
168 }  // namespace gpu
169 }  // namespace tflite
170