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