blob: ffad4d331d645652b7d1a4df3321b46805763602 [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
XNNPACK Teamb455b122019-09-27 18:10:33 -070024
Marat Dukhan08b7a972020-07-14 18:17:29 -070025static void global_average_pooling_qu8(benchmark::State& state) {
XNNPACK Teamb455b122019-09-27 18:10:33 -070026 const size_t batch_size = state.range(0);
27 const size_t input_height = state.range(1);
28 const size_t input_width = state.range(2);
29 const size_t channels = state.range(3);
30
31 std::random_device random_device;
32 auto rng = std::mt19937(random_device());
Marat Dukhan5ce30d92020-04-14 03:31:26 -070033 auto u8rng = std::bind(std::uniform_int_distribution<uint32_t>(0, std::numeric_limits<uint8_t>::max()), rng);
XNNPACK Teamb455b122019-09-27 18:10:33 -070034
35 std::vector<uint8_t> input(batch_size * input_height * input_width * channels);
36 std::generate(input.begin(), input.end(), std::ref(u8rng));
37 std::vector<uint8_t> output(batch_size * channels);
38
Marat Dukhan04f03be2019-11-19 12:36:47 -080039 xnn_status status = xnn_initialize(nullptr /* allocator */);
XNNPACK Teamb455b122019-09-27 18:10:33 -070040 if (status != xnn_status_success) {
41 state.SkipWithError("failed to initialize XNNPACK");
42 }
43
44 xnn_operator_t global_pooling_op = nullptr;
Marat Dukhan08b7a972020-07-14 18:17:29 -070045 status = xnn_create_global_average_pooling_nwc_qu8(
XNNPACK Teamb455b122019-09-27 18:10:33 -070046 channels, channels /* input stride */, channels /* output stride */,
47 127 /* input zero point */, 0.75f /* input scale */,
48 127 /* output zero point */, 1.25f /* output scale */,
49 0, 255,
50 0 /* flags */, &global_pooling_op);
51 if (status != xnn_status_success) {
52 state.SkipWithError("failed to create Global Average Pooling operator");
53 }
54
Marat Dukhan08b7a972020-07-14 18:17:29 -070055 status = xnn_setup_global_average_pooling_nwc_qu8(
XNNPACK Teamb455b122019-09-27 18:10:33 -070056 global_pooling_op,
57 batch_size, input_height * input_width,
58 input.data(), output.data(),
59 nullptr /* thread pool */);
60 if (status != xnn_status_success) {
61 state.SkipWithError("failed to setup Global Average Pooling operator");
62 }
63
64 for (auto _ : state) {
65 xnn_run_operator(global_pooling_op, nullptr /* thread pool */);
66 }
67
68 status = xnn_delete_operator(global_pooling_op);
69 if (status != xnn_status_success) {
70 state.SkipWithError("failed to delete Global Average Pooling operator");
71 }
72 global_pooling_op = nullptr;
73
Frank Barchardbb4c18b2019-09-30 11:05:52 -070074 state.counters["Freq"] = benchmark::utils::GetCurrentCpuFrequency();
XNNPACK Teamb455b122019-09-27 18:10:33 -070075 state.counters["bytes"] = benchmark::Counter(
76 uint64_t(state.iterations()) *
77 batch_size * (input_height * input_width + 1) * channels * sizeof(uint8_t),
78 benchmark::Counter::kIsRate);
79}
80
Marat Dukhan08b7a972020-07-14 18:17:29 -070081#endif // XNN_NO_QU8_OPERATORS
Frank Barchard0ccccf12020-06-22 15:21:45 -070082
83#ifndef XNN_NO_F16_OPERATORS
84
Frank Barchard0c849732020-06-12 13:31:32 -070085static void global_average_pooling_f16(benchmark::State& state) {
86 if (!benchmark::utils::CheckNEONFP16ARITH(state)) {
87 return;
88 }
89 const size_t batch_size = state.range(0);
90 const size_t input_height = state.range(1);
91 const size_t input_width = state.range(2);
92 const size_t channels = state.range(3);
93
94 std::random_device random_device;
95 auto rng = std::mt19937(random_device());
96 auto f32rng = std::bind(std::uniform_real_distribution<float>(0.1f, 1.0f), rng);
97 auto f16rng = std::bind(fp16_ieee_from_fp32_value, f32rng);
98
99 std::vector<uint16_t> input(batch_size * input_height * input_width * channels);
100 std::generate(input.begin(), input.end(), std::ref(f16rng));
101 std::vector<uint16_t> output(batch_size * channels);
102
103 xnn_status status = xnn_initialize(nullptr /* allocator */);
104 if (status != xnn_status_success) {
105 state.SkipWithError("failed to initialize XNNPACK");
106 }
107
108 xnn_operator_t global_pooling_op = nullptr;
109 status = xnn_create_global_average_pooling_nwc_f16(
110 channels, channels /* input stride */, channels /* output stride */,
111 -std::numeric_limits<float>::infinity(), +std::numeric_limits<float>::infinity(),
112 0 /* flags */, &global_pooling_op);
113 if (status != xnn_status_success) {
114 state.SkipWithError("failed to create Global Average Pooling operator");
115 }
116
117 status = xnn_setup_global_average_pooling_nwc_f16(
118 global_pooling_op,
119 batch_size, input_height * input_width,
120 input.data(), output.data(),
121 nullptr /* thread pool */);
122 if (status != xnn_status_success) {
123 state.SkipWithError("failed to setup Global Average Pooling operator");
124 }
125
126 for (auto _ : state) {
127 xnn_run_operator(global_pooling_op, nullptr /* thread pool */);
128 }
129
130 status = xnn_delete_operator(global_pooling_op);
131 if (status != xnn_status_success) {
132 state.SkipWithError("failed to delete Global Average Pooling operator");
133 }
134 global_pooling_op = nullptr;
135
136 state.counters["Freq"] = benchmark::utils::GetCurrentCpuFrequency();
137 state.counters["bytes"] = benchmark::Counter(
138 uint64_t(state.iterations()) *
139 batch_size * (input_height * input_width + 1) * channels * sizeof(uint16_t),
140 benchmark::Counter::kIsRate);
141}
142
Frank Barchard0ccccf12020-06-22 15:21:45 -0700143#endif // XNN_NO_F16_OPERATORS
144
Frank Barchard03252442020-06-12 10:47:30 -0700145static void global_average_pooling_f32(benchmark::State& state) {
146 const size_t batch_size = state.range(0);
147 const size_t input_height = state.range(1);
148 const size_t input_width = state.range(2);
149 const size_t channels = state.range(3);
150
151 std::random_device random_device;
152 auto rng = std::mt19937(random_device());
153 auto f32rng = std::bind(std::uniform_real_distribution<float>(), rng);
154
155 std::vector<float> input(batch_size * input_height * input_width * channels);
156 std::generate(input.begin(), input.end(), std::ref(f32rng));
157 std::vector<float> 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_f32(
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_f32(
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(float),
196 benchmark::Counter::kIsRate);
197}
198
XNNPACK Teamb455b122019-09-27 18:10:33 -0700199static void ImageNetArguments(benchmark::internal::Benchmark* b) {
200 b->ArgNames({"N", "H", "W", "C"});
201
202 /* N IH IW C */
203 b->Args({1, 7, 7, 1000});
204 b->Args({1, 13, 13, 1000});
205}
206
Marat Dukhan08b7a972020-07-14 18:17:29 -0700207#ifndef XNN_NO_QU8_OPERATORS
208BENCHMARK(global_average_pooling_qu8)->Apply(ImageNetArguments)->UseRealTime();
209#endif // XNN_NO_QU8_OPERATORS
Frank Barchard0ccccf12020-06-22 15:21:45 -0700210#ifndef XNN_NO_F16_OPERATORS
Frank Barchard0c849732020-06-12 13:31:32 -0700211BENCHMARK(global_average_pooling_f16)->Apply(ImageNetArguments)->UseRealTime();
Frank Barchard0ccccf12020-06-22 15:21:45 -0700212#endif // XNN_NO_F16_OPERATORS
Frank Barchard03252442020-06-12 10:47:30 -0700213BENCHMARK(global_average_pooling_f32)->Apply(ImageNetArguments)->UseRealTime();
XNNPACK Teamb455b122019-09-27 18:10:33 -0700214
215#ifndef XNNPACK_BENCHMARK_NO_MAIN
216BENCHMARK_MAIN();
217#endif