ONE - On-device Neural Engine
Loading...
Searching...
No Matches
TestUtils.cpp
Go to the documentation of this file.
1/*
2 * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
3 * Copyright 2017 The TensorFlow Authors. All Rights Reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#include "kernels/TestUtils.h"
19
20#include <stdexcept>
21
22namespace luci_interpreter
23{
24namespace kernels
25{
26namespace testing
27{
28
29using ::testing::FloatNear;
30using ::testing::DoubleNear;
31using ::testing::Matcher;
32
33Tensor makeOutputTensor(DataType element_type) { return Tensor(element_type, {}, {}, ""); }
34
35Tensor makeOutputTensor(DataType element_type, float scale, int32_t zero_point)
36{
37 return Tensor(element_type, {}, {{scale}, {zero_point}}, "");
38}
39
40std::vector<float> dequantizeTensorData(const Tensor &tensor)
41{
42 if (tensor.element_type() == DataType::U8)
43 {
44 std::vector<uint8_t> data = extractTensorData<uint8_t>(tensor);
45 return dequantize(data.data(), data.size(), tensor.scale(), tensor.zero_point());
46 }
47 if (tensor.element_type() == DataType::S8)
48 {
49 std::vector<int8_t> data = extractTensorData<int8_t>(tensor);
50 return dequantize(data.data(), data.size(), tensor.scale(), tensor.zero_point());
51 }
52 else if (tensor.element_type() == DataType::S16)
53 {
54 // S16 quantization is symmetric, so zero point should be zero.
55 for (auto zp : tensor.zero_points())
56 {
57 (void)zp;
58 assert(zp == 0);
59 }
60
61 std::vector<int16_t> data = extractTensorData<int16_t>(tensor);
62 if (tensor.scales().size() == 1)
63 {
64 return dequantize(data.data(), data.size(), tensor.scale(), 0);
65 }
66
67 // quantize_dimension breaks shape into two parts:
68 // inner dimensions that contains continuous data with one quantization type
69 // outer dimensions that contains other dimensions
70 const Shape shape = tensor.shape();
71 const int32_t quantized_dimension = tensor.quantized_dimension();
72 assert(quantized_dimension < shape.num_dims());
73 size_t outer_dims_size = 1;
74 int32_t quant_dim_size = shape.dim(quantized_dimension);
75 size_t inner_dims_size = 1;
76 assert(quant_dim_size == tensor.scales().size());
77
78 for (int i = 0; i < quantized_dimension; ++i)
79 outer_dims_size *= shape.dim(i);
80 for (int i = quantized_dimension + 1; i < shape.num_dims(); ++i)
81 inner_dims_size *= shape.dim(i);
82
84
85 std::vector<float> dequantized_data;
86 dequantized_data.reserve(shape.num_elements());
87 for (size_t outer_it = 0; outer_it < outer_dims_size; ++outer_it)
88 for (int32_t channel = 0; channel < quant_dim_size; ++channel)
89 {
90 float scale = tensor.scales()[channel];
91 size_t offset = inner_dims_size * (quant_dim_size * outer_it + channel);
92 std::vector<float> part_dequantized_data =
93 dequantize(data.data() + offset, inner_dims_size, scale, 0);
96 }
97 return dequantized_data;
98 }
99 else
100 {
101 throw std::runtime_error("Unsupported type.");
102 }
103}
104
105Matcher<std::vector<float>> FloatArrayNear(const std::vector<float> &values, float max_abs_error)
106{
107 std::vector<Matcher<float>> matchers;
108 matchers.reserve(values.size());
109 for (const float v : values)
110 {
111 matchers.emplace_back(FloatNear(v, max_abs_error));
112 }
114}
115
116Matcher<std::vector<double>> DoubleArrayNear(const std::vector<double> &values,
117 double max_abs_error)
118{
119 std::vector<Matcher<double>> matchers;
120 matchers.reserve(values.size());
121 for (const double v : values)
122 {
123 matchers.emplace_back(DoubleNear(v, max_abs_error));
124 }
126}
127
128std::vector<int32_t> extractTensorShape(const Tensor &tensor)
129{
130 std::vector<int32_t> result;
131 int dims = tensor.shape().num_dims();
132 for (int i = 0; i < dims; i++)
133 {
134 result.push_back(tensor.shape().dim(i));
135 }
136 return result;
137}
138
139} // namespace testing
140} // namespace kernels
141} // namespace luci_interpreter
int32_t dim(int i) const
Definition Tensor.h:41
int32_t num_elements() const
Definition Tensor.h:53
int num_dims() const
Definition Tensor.h:39
__global uchar * offset(const Image *img, int x, int y)
Definition helpers.h:540
const T * data(const std::vector< T, Alloc > &v)
Tensor makeOutputTensor(DataType element_type)
Definition TestUtils.cpp:33
std::vector< float > dequantize(const T *data, size_t num_elements, float scale, int32_t zero_point)
Definition TestUtils.h:205
std::vector< int32_t > extractTensorShape(const Tensor &tensor)
Matcher< std::vector< double > > DoubleArrayNear(const std::vector< double > &values, double max_abs_error)
std::vector< float > dequantizeTensorData(const Tensor &tensor)
Definition TestUtils.cpp:40
Matcher< std::vector< float > > FloatArrayNear(const std::vector< float > &values, float max_abs_error)
DataType
"scalar" value type
Definition DataType.h:32
T must_cast(loco::Node *node)