• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2019 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 #include <algorithm>
16 #include <cmath>
17 #include <cstdlib>
18 #include <functional>
19 #include <iterator>
20 #include <limits>
21 #include <random>
22 #include <string>
23 #include <vector>
24 
25 #include <gtest/gtest.h>
26 #include "tensorflow/lite/kernels/internal/optimized/integer_ops/pooling.h"
27 #include "tensorflow/lite/kernels/internal/reference/integer_ops/pooling.h"
28 #include "tensorflow/lite/kernels/internal/test_util.h"
29 
30 namespace tflite {
31 namespace {
32 
33 // Runs the reference and optimized MaxPool functions and asserts the values
34 // are the same.
RunOneMaxPoolTest(const PoolParams & params,const RuntimeShape & input_shape,const int8 * input_data,const RuntimeShape & output_shape)35 void RunOneMaxPoolTest(const PoolParams& params,
36                        const RuntimeShape& input_shape, const int8* input_data,
37                        const RuntimeShape& output_shape) {
38   const int buffer_size = output_shape.FlatSize();
39   std::vector<int8> optimized_maxpool_output(buffer_size);
40   std::vector<int8> reference_maxpool_output(buffer_size);
41 
42   reference_integer_ops::MaxPool(params, input_shape, input_data, output_shape,
43                                  reference_maxpool_output.data());
44   optimized_integer_ops::MaxPool(params, input_shape, input_data, output_shape,
45                                  optimized_maxpool_output.data());
46 
47   for (int i = 0; i < buffer_size; i++) {
48     ASSERT_TRUE(reference_maxpool_output[i] == optimized_maxpool_output[i]);
49   }
50 }
51 
52 // Creates random input shape (batch, height, width, depth), then computes
53 // output shape based on value of `padding_same`:
54 // `padding_same` == true, calculate output with padding == "SAME"
55 // `padding_same` == false, calculate output with padding == "VALID"
56 // With input/output shapes computed, fills the input data and calls the
57 // test function.
CreateDataAndRunMaxPool(bool padding_same)58 void CreateDataAndRunMaxPool(bool padding_same) {
59   const int batch = UniformRandomInt(1, 2);
60   const int input_depth = UniformRandomInt(1, 700);
61   const int output_depth = input_depth;
62   const int input_width_offset = UniformRandomInt(1, 30);
63   const int input_height_offset = UniformRandomInt(1, 30);
64   const int stride_width = UniformRandomInt(1, 10);
65   const int stride_height = UniformRandomInt(1, 10);
66   const int filter_width = UniformRandomInt(1, 10);
67   const int filter_height = UniformRandomInt(1, 10);
68   const int input_width = input_width_offset + filter_width;
69   const int input_height = input_height_offset + filter_height;
70   const int output_width =
71       padding_same ? (input_width + stride_width - 1) / stride_width
72                    : (input_width - filter_width + stride_width) / stride_width;
73   const int output_height =
74       padding_same
75           ? (input_height + stride_height - 1) / stride_height
76           : (input_height - filter_height + stride_height) / stride_height;
77 
78   auto input_shape =
79       RuntimeShape({batch, input_height, input_width, input_depth});
80   auto output_shape =
81       RuntimeShape({batch, output_height, output_width, output_depth});
82   const int buffer_size = input_shape.FlatSize();
83   std::vector<int8> input_data(buffer_size);
84   FillRandom(&input_data);
85 
86   PoolParams params;
87   params.stride_height = stride_height;
88   params.stride_width = stride_width;
89   params.filter_height = filter_height;
90   params.filter_width = filter_width;
91   params.quantized_activation_min =
92       static_cast<int8_t>(std::numeric_limits<int8_t>::lowest());
93   params.quantized_activation_max =
94       static_cast<int8_t>(std::numeric_limits<int8_t>::max());
95   auto compute_padding = [](int stride, int in_size, int filter_size,
96                             int out_size) {
97     int padding = ((out_size - 1) * stride + filter_size - in_size) / 2;
98     return padding > 0 ? padding : 0;
99   };
100   params.padding_values.width =
101       compute_padding(stride_width, input_width, filter_width, output_width);
102   params.padding_values.height = compute_padding(stride_height, input_height,
103                                                  filter_height, output_height);
104   RunOneMaxPoolTest(params, input_shape, input_data.data(), output_shape);
105 }
106 
TEST(TestMaxPool,SymmetricQuantMaxPool)107 TEST(TestMaxPool, SymmetricQuantMaxPool) {
108   const int kTestsToRun = 10;
109   for (int i = 0; i < kTestsToRun; i++) {
110     CreateDataAndRunMaxPool(/*padding_same=*/true);
111     CreateDataAndRunMaxPool(/*padding_same=*/false);
112   }
113 }
114 
115 }  // namespace
116 }  // namespace tflite
117