blob: 517c6794442dee9af9914d424e665090e910a6b7 [file] [log] [blame]
XNNPACK Teamb455b122019-09-27 18:10:33 -07001// Copyright (c) Facebook, Inc. and its affiliates.
2// All rights reserved.
3//
4// Copyright 2019 Google LLC
5//
6// This source code is licensed under the BSD-style license found in the
7// LICENSE file in the root directory of this source tree.
8
9#include <algorithm>
10#include <cfloat>
11#include <cmath>
12#include <functional>
Marat Dukhan5ce30d92020-04-14 03:31:26 -070013#include <limits>
XNNPACK Teamb455b122019-09-27 18:10:33 -070014#include <random>
15#include <vector>
16
17#include <xnnpack.h>
18
19#include <benchmark/benchmark.h>
Frank Barchard0c849732020-06-12 13:31:32 -070020#include <fp16.h>
Frank Barchardbb4c18b2019-09-30 11:05:52 -070021#include "bench/utils.h"
XNNPACK Teamb455b122019-09-27 18:10:33 -070022
Marat Dukhan08b7a972020-07-14 18:17:29 -070023#ifndef XNN_NO_QU8_OPERATORS
Marat Dukhan08b7a972020-07-14 18:17:29 -070024static void global_average_pooling_qu8(benchmark::State& state) {
XNNPACK Teamb455b122019-09-27 18:10:33 -070025 const size_t batch_size = state.range(0);
26 const size_t input_height = state.range(1);
27 const size_t input_width = state.range(2);
28 const size_t channels = state.range(3);
29
30 std::random_device random_device;
31 auto rng = std::mt19937(random_device());
Marat Dukhan44f0ca72020-08-02 21:46:58 -070032 auto u8rng = std::bind(std::uniform_int_distribution<uint32_t>(0, std::numeric_limits<uint8_t>::max()), std::ref(rng));
XNNPACK Teamb455b122019-09-27 18:10:33 -070033
34 std::vector<uint8_t> input(batch_size * input_height * input_width * channels);
35 std::generate(input.begin(), input.end(), std::ref(u8rng));
36 std::vector<uint8_t> output(batch_size * channels);
37
Marat Dukhan04f03be2019-11-19 12:36:47 -080038 xnn_status status = xnn_initialize(nullptr /* allocator */);
XNNPACK Teamb455b122019-09-27 18:10:33 -070039 if (status != xnn_status_success) {
40 state.SkipWithError("failed to initialize XNNPACK");
41 }
42
43 xnn_operator_t global_pooling_op = nullptr;
Marat Dukhan08b7a972020-07-14 18:17:29 -070044 status = xnn_create_global_average_pooling_nwc_qu8(
XNNPACK Teamb455b122019-09-27 18:10:33 -070045 channels, channels /* input stride */, channels /* output stride */,
46 127 /* input zero point */, 0.75f /* input scale */,
47 127 /* output zero point */, 1.25f /* output scale */,
48 0, 255,
49 0 /* flags */, &global_pooling_op);
50 if (status != xnn_status_success) {
51 state.SkipWithError("failed to create Global Average Pooling operator");
52 }
53
Marat Dukhan08b7a972020-07-14 18:17:29 -070054 status = xnn_setup_global_average_pooling_nwc_qu8(
XNNPACK Teamb455b122019-09-27 18:10:33 -070055 global_pooling_op,
56 batch_size, input_height * input_width,
57 input.data(), output.data(),
58 nullptr /* thread pool */);
59 if (status != xnn_status_success) {
60 state.SkipWithError("failed to setup Global Average Pooling operator");
61 }
62
63 for (auto _ : state) {
64 xnn_run_operator(global_pooling_op, nullptr /* thread pool */);
65 }
66
67 status = xnn_delete_operator(global_pooling_op);
68 if (status != xnn_status_success) {
69 state.SkipWithError("failed to delete Global Average Pooling operator");
70 }
71 global_pooling_op = nullptr;
72
Frank Barchardbb4c18b2019-09-30 11:05:52 -070073 state.counters["Freq"] = benchmark::utils::GetCurrentCpuFrequency();
XNNPACK Teamb455b122019-09-27 18:10:33 -070074 state.counters["bytes"] = benchmark::Counter(
75 uint64_t(state.iterations()) *
76 batch_size * (input_height * input_width + 1) * channels * sizeof(uint8_t),
77 benchmark::Counter::kIsRate);
78}
Marat Dukhan08b7a972020-07-14 18:17:29 -070079#endif // XNN_NO_QU8_OPERATORS
Frank Barchard0ccccf12020-06-22 15:21:45 -070080
Marat Dukhan9e0b5392020-08-07 02:29:34 -070081#ifndef XNN_NO_QS8_OPERATORS
82static void global_average_pooling_qs8(benchmark::State& state) {
83 const size_t batch_size = state.range(0);
84 const size_t input_height = state.range(1);
85 const size_t input_width = state.range(2);
86 const size_t channels = state.range(3);
Frank Barchard0ccccf12020-06-22 15:21:45 -070087
Marat Dukhan9e0b5392020-08-07 02:29:34 -070088 std::random_device random_device;
89 auto rng = std::mt19937(random_device());
90 auto i8rng = std::bind(
91 std::uniform_int_distribution<uint32_t>(std::numeric_limits<int8_t>::min(), std::numeric_limits<int8_t>::max()), std::ref(rng));
92
93 std::vector<int8_t> input(batch_size * input_height * input_width * channels);
94 std::generate(input.begin(), input.end(), std::ref(i8rng));
95 std::vector<int8_t> output(batch_size * channels);
96
97 xnn_status status = xnn_initialize(nullptr /* allocator */);
98 if (status != xnn_status_success) {
99 state.SkipWithError("failed to initialize XNNPACK");
100 }
101
102 xnn_operator_t global_pooling_op = nullptr;
103 status = xnn_create_global_average_pooling_nwc_qs8(
104 channels, channels /* input stride */, channels /* output stride */,
105 -1 /* input zero point */, 0.75f /* input scale */,
106 -1 /* output zero point */, 1.25f /* output scale */,
107 -128, 127,
108 0 /* flags */, &global_pooling_op);
109 if (status != xnn_status_success) {
110 state.SkipWithError("failed to create Global Average Pooling operator");
111 }
112
113 status = xnn_setup_global_average_pooling_nwc_qs8(
114 global_pooling_op,
115 batch_size, input_height * input_width,
116 input.data(), output.data(),
117 nullptr /* thread pool */);
118 if (status != xnn_status_success) {
119 state.SkipWithError("failed to setup Global Average Pooling operator");
120 }
121
122 for (auto _ : state) {
123 xnn_run_operator(global_pooling_op, nullptr /* thread pool */);
124 }
125
126 status = xnn_delete_operator(global_pooling_op);
127 if (status != xnn_status_success) {
128 state.SkipWithError("failed to delete Global Average Pooling operator");
129 }
130 global_pooling_op = nullptr;
131
132 state.counters["Freq"] = benchmark::utils::GetCurrentCpuFrequency();
133 state.counters["bytes"] = benchmark::Counter(
134 uint64_t(state.iterations()) *
135 batch_size * (input_height * input_width + 1) * channels * sizeof(int8_t),
136 benchmark::Counter::kIsRate);
137}
138#endif // XNN_NO_QS8_OPERATORS
139
140#ifndef XNN_NO_F16_OPERATORS
Frank Barchard0c849732020-06-12 13:31:32 -0700141static void global_average_pooling_f16(benchmark::State& state) {
142 if (!benchmark::utils::CheckNEONFP16ARITH(state)) {
143 return;
144 }
145 const size_t batch_size = state.range(0);
146 const size_t input_height = state.range(1);
147 const size_t input_width = state.range(2);
148 const size_t channels = state.range(3);
149
150 std::random_device random_device;
151 auto rng = std::mt19937(random_device());
Marat Dukhan44f0ca72020-08-02 21:46:58 -0700152 auto f32rng = std::bind(std::uniform_real_distribution<float>(0.1f, 1.0f), std::ref(rng));
Frank Barchard0c849732020-06-12 13:31:32 -0700153 auto f16rng = std::bind(fp16_ieee_from_fp32_value, f32rng);
154
155 std::vector<uint16_t> input(batch_size * input_height * input_width * channels);
156 std::generate(input.begin(), input.end(), std::ref(f16rng));
157 std::vector<uint16_t> output(batch_size * channels);
158
159 xnn_status status = xnn_initialize(nullptr /* allocator */);
160 if (status != xnn_status_success) {
161 state.SkipWithError("failed to initialize XNNPACK");
162 }
163
164 xnn_operator_t global_pooling_op = nullptr;
165 status = xnn_create_global_average_pooling_nwc_f16(
166 channels, channels /* input stride */, channels /* output stride */,
167 -std::numeric_limits<float>::infinity(), +std::numeric_limits<float>::infinity(),
168 0 /* flags */, &global_pooling_op);
169 if (status != xnn_status_success) {
170 state.SkipWithError("failed to create Global Average Pooling operator");
171 }
172
173 status = xnn_setup_global_average_pooling_nwc_f16(
174 global_pooling_op,
175 batch_size, input_height * input_width,
176 input.data(), output.data(),
177 nullptr /* thread pool */);
178 if (status != xnn_status_success) {
179 state.SkipWithError("failed to setup Global Average Pooling operator");
180 }
181
182 for (auto _ : state) {
183 xnn_run_operator(global_pooling_op, nullptr /* thread pool */);
184 }
185
186 status = xnn_delete_operator(global_pooling_op);
187 if (status != xnn_status_success) {
188 state.SkipWithError("failed to delete Global Average Pooling operator");
189 }
190 global_pooling_op = nullptr;
191
192 state.counters["Freq"] = benchmark::utils::GetCurrentCpuFrequency();
193 state.counters["bytes"] = benchmark::Counter(
194 uint64_t(state.iterations()) *
195 batch_size * (input_height * input_width + 1) * channels * sizeof(uint16_t),
196 benchmark::Counter::kIsRate);
197}
Frank Barchard0ccccf12020-06-22 15:21:45 -0700198#endif // XNN_NO_F16_OPERATORS
199
Frank Barchard03252442020-06-12 10:47:30 -0700200static void global_average_pooling_f32(benchmark::State& state) {
201 const size_t batch_size = state.range(0);
202 const size_t input_height = state.range(1);
203 const size_t input_width = state.range(2);
204 const size_t channels = state.range(3);
205
206 std::random_device random_device;
207 auto rng = std::mt19937(random_device());
Marat Dukhan44f0ca72020-08-02 21:46:58 -0700208 auto f32rng = std::bind(std::uniform_real_distribution<float>(), std::ref(rng));
Frank Barchard03252442020-06-12 10:47:30 -0700209
210 std::vector<float> input(batch_size * input_height * input_width * channels);
211 std::generate(input.begin(), input.end(), std::ref(f32rng));
212 std::vector<float> output(batch_size * channels);
213
214 xnn_status status = xnn_initialize(nullptr /* allocator */);
215 if (status != xnn_status_success) {
216 state.SkipWithError("failed to initialize XNNPACK");
217 }
218
219 xnn_operator_t global_pooling_op = nullptr;
220 status = xnn_create_global_average_pooling_nwc_f32(
221 channels, channels /* input stride */, channels /* output stride */,
222 -std::numeric_limits<float>::infinity(), +std::numeric_limits<float>::infinity(),
223 0 /* flags */, &global_pooling_op);
224 if (status != xnn_status_success) {
225 state.SkipWithError("failed to create Global Average Pooling operator");
226 }
227
228 status = xnn_setup_global_average_pooling_nwc_f32(
229 global_pooling_op,
230 batch_size, input_height * input_width,
231 input.data(), output.data(),
232 nullptr /* thread pool */);
233 if (status != xnn_status_success) {
234 state.SkipWithError("failed to setup Global Average Pooling operator");
235 }
236
237 for (auto _ : state) {
238 xnn_run_operator(global_pooling_op, nullptr /* thread pool */);
239 }
240
241 status = xnn_delete_operator(global_pooling_op);
242 if (status != xnn_status_success) {
243 state.SkipWithError("failed to delete Global Average Pooling operator");
244 }
245 global_pooling_op = nullptr;
246
247 state.counters["Freq"] = benchmark::utils::GetCurrentCpuFrequency();
248 state.counters["bytes"] = benchmark::Counter(
249 uint64_t(state.iterations()) *
250 batch_size * (input_height * input_width + 1) * channels * sizeof(float),
251 benchmark::Counter::kIsRate);
252}
253
XNNPACK Teamb455b122019-09-27 18:10:33 -0700254static void ImageNetArguments(benchmark::internal::Benchmark* b) {
255 b->ArgNames({"N", "H", "W", "C"});
256
257 /* N IH IW C */
258 b->Args({1, 7, 7, 1000});
259 b->Args({1, 13, 13, 1000});
260}
261
Marat Dukhan08b7a972020-07-14 18:17:29 -0700262#ifndef XNN_NO_QU8_OPERATORS
263BENCHMARK(global_average_pooling_qu8)->Apply(ImageNetArguments)->UseRealTime();
264#endif // XNN_NO_QU8_OPERATORS
Marat Dukhan9e0b5392020-08-07 02:29:34 -0700265#ifndef XNN_NO_QS8_OPERATORS
266BENCHMARK(global_average_pooling_qs8)->Apply(ImageNetArguments)->UseRealTime();
267#endif // XNN_NO_QS8_OPERATORS
Frank Barchard0ccccf12020-06-22 15:21:45 -0700268#ifndef XNN_NO_F16_OPERATORS
Frank Barchard0c849732020-06-12 13:31:32 -0700269BENCHMARK(global_average_pooling_f16)->Apply(ImageNetArguments)->UseRealTime();
Frank Barchard0ccccf12020-06-22 15:21:45 -0700270#endif // XNN_NO_F16_OPERATORS
Frank Barchard03252442020-06-12 10:47:30 -0700271BENCHMARK(global_average_pooling_f32)->Apply(ImageNetArguments)->UseRealTime();
XNNPACK Teamb455b122019-09-27 18:10:33 -0700272
273#ifndef XNNPACK_BENCHMARK_NO_MAIN
274BENCHMARK_MAIN();
275#endif