• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <fenv.h>
18 #include <math.h>
19 
20 #include <benchmark/benchmark.h>
21 #include "util.h"
22 
23 static const double values[] = { 1234.0, nan(""), HUGE_VAL, 0.0 };
24 static const char* names[] = { "1234.0", "nan", "HUGE_VAL", "0.0" };
25 
SetLabel(benchmark::State & state)26 static void SetLabel(benchmark::State& state) {
27   state.SetLabel(names[state.range(0)]);
28 }
29 
30 // Avoid optimization.
31 volatile double d;
32 volatile double v;
33 volatile float f;
34 
35 static float zero = 0.0f;
36 static double zerod = 0.0f;
37 
BM_math_sqrt(benchmark::State & state)38 static void BM_math_sqrt(benchmark::State& state) {
39   d = 0.0;
40   v = 2.0;
41   while (state.KeepRunning()) {
42     d += sqrt(v);
43   }
44 }
45 BIONIC_BENCHMARK(BM_math_sqrt);
46 
BM_math_log10(benchmark::State & state)47 static void BM_math_log10(benchmark::State& state) {
48   d = 0.0;
49   v = 1234.0;
50   while (state.KeepRunning()) {
51     d += log10(v);
52   }
53 }
54 BIONIC_BENCHMARK(BM_math_log10);
55 
BM_math_logb(benchmark::State & state)56 static void BM_math_logb(benchmark::State& state) {
57   d = 0.0;
58   v = 1234.0;
59   while (state.KeepRunning()) {
60     d += logb(v);
61   }
62 }
63 BIONIC_BENCHMARK(BM_math_logb);
64 
BM_math_isfinite_macro(benchmark::State & state)65 static void BM_math_isfinite_macro(benchmark::State& state) {
66   d = 0.0;
67   v = values[state.range(0)];
68   while (state.KeepRunning()) {
69     d += isfinite(v);
70   }
71   SetLabel(state);
72 }
73 BIONIC_BENCHMARK_WITH_ARG(BM_math_isfinite_macro, "MATH_COMMON");
74 
BM_math_isfinite(benchmark::State & state)75 static void BM_math_isfinite(benchmark::State& state) {
76   d = 0.0;
77   v = values[state.range(0)];
78   while (state.KeepRunning()) {
79     d += isfinite(v);
80   }
81   SetLabel(state);
82 }
83 BIONIC_BENCHMARK_WITH_ARG(BM_math_isfinite, "MATH_COMMON");
84 
BM_math_isinf_macro(benchmark::State & state)85 static void BM_math_isinf_macro(benchmark::State& state) {
86   d = 0.0;
87   v = values[state.range(0)];
88   while (state.KeepRunning()) {
89     d += isinf(v);
90   }
91   SetLabel(state);
92 }
93 BIONIC_BENCHMARK_WITH_ARG(BM_math_isinf_macro, "MATH_COMMON");
94 
BM_math_isinf(benchmark::State & state)95 static void BM_math_isinf(benchmark::State& state) {
96   d = 0.0;
97   v = values[state.range(0)];
98   while (state.KeepRunning()) {
99     d += (isinf)(v);
100   }
101   SetLabel(state);
102 }
103 BIONIC_BENCHMARK_WITH_ARG(BM_math_isinf, "MATH_COMMON");
104 
BM_math_isnan_macro(benchmark::State & state)105 static void BM_math_isnan_macro(benchmark::State& state) {
106   d = 0.0;
107   v = values[state.range(0)];
108   while (state.KeepRunning()) {
109     d += isnan(v);
110   }
111   SetLabel(state);
112 }
113 BIONIC_BENCHMARK_WITH_ARG(BM_math_isnan_macro, "MATH_COMMON");
114 
BM_math_isnan(benchmark::State & state)115 static void BM_math_isnan(benchmark::State& state) {
116   d = 0.0;
117   v = values[state.range(0)];
118   while (state.KeepRunning()) {
119     d += (isnan)(v);
120   }
121   SetLabel(state);
122 }
123 BIONIC_BENCHMARK_WITH_ARG(BM_math_isnan, "MATH_COMMON");
124 
BM_math_isnormal_macro(benchmark::State & state)125 static void BM_math_isnormal_macro(benchmark::State& state) {
126   d = 0.0;
127   v = values[state.range(0)];
128   while (state.KeepRunning()) {
129     d += isnormal(v);
130   }
131   SetLabel(state);
132 }
133 BIONIC_BENCHMARK_WITH_ARG(BM_math_isnormal_macro, "MATH_COMMON");
134 
BM_math_isnormal(benchmark::State & state)135 static void BM_math_isnormal(benchmark::State& state) {
136   d = 0.0;
137   v = values[state.range(0)];
138   while (state.KeepRunning()) {
139     d += isnormal(v);
140   }
141   SetLabel(state);
142 }
143 BIONIC_BENCHMARK_WITH_ARG(BM_math_isnormal, "MATH_COMMON");
144 
BM_math_sin_fast(benchmark::State & state)145 static void BM_math_sin_fast(benchmark::State& state) {
146   d = 1.0;
147   while (state.KeepRunning()) {
148     d += sin(d);
149   }
150 }
151 BIONIC_BENCHMARK(BM_math_sin_fast);
152 
BM_math_sin_feupdateenv(benchmark::State & state)153 static void BM_math_sin_feupdateenv(benchmark::State& state) {
154   d = 1.0;
155   while (state.KeepRunning()) {
156     fenv_t __libc_save_rm;
157     feholdexcept(&__libc_save_rm);
158     fesetround(FE_TONEAREST);
159     d += sin(d);
160     feupdateenv(&__libc_save_rm);
161   }
162 }
163 BIONIC_BENCHMARK(BM_math_sin_feupdateenv);
164 
BM_math_sin_fesetenv(benchmark::State & state)165 static void BM_math_sin_fesetenv(benchmark::State& state) {
166   d = 1.0;
167   while (state.KeepRunning()) {
168     fenv_t __libc_save_rm;
169     feholdexcept(&__libc_save_rm);
170     fesetround(FE_TONEAREST);
171     d += sin(d);
172     fesetenv(&__libc_save_rm);
173   }
174 }
175 BIONIC_BENCHMARK(BM_math_sin_fesetenv);
176 
BM_math_fpclassify(benchmark::State & state)177 static void BM_math_fpclassify(benchmark::State& state) {
178   d = 0.0;
179   v = values[state.range(0)];
180   while (state.KeepRunning()) {
181     d += fpclassify(v);
182   }
183   SetLabel(state);
184 }
185 BIONIC_BENCHMARK_WITH_ARG(BM_math_fpclassify, "MATH_COMMON");
186 
BM_math_signbit_macro(benchmark::State & state)187 static void BM_math_signbit_macro(benchmark::State& state) {
188   d = 0.0;
189   v = values[state.range(0)];
190   while (state.KeepRunning()) {
191     d += signbit(v);
192   }
193   SetLabel(state);
194 }
195 BIONIC_BENCHMARK_WITH_ARG(BM_math_signbit_macro, "MATH_COMMON");
196 
BM_math_signbit(benchmark::State & state)197 static void BM_math_signbit(benchmark::State& state) {
198   d = 0.0;
199   v = values[state.range(0)];
200   while (state.KeepRunning()) {
201     d += signbit(v);
202   }
203   SetLabel(state);
204 }
205 BIONIC_BENCHMARK_WITH_ARG(BM_math_signbit, "MATH_COMMON");
206 
BM_math_fabs_macro(benchmark::State & state)207 static void BM_math_fabs_macro(benchmark::State& state) {
208   d = 0.0;
209   v = values[state.range(0)];
210   while (state.KeepRunning()) {
211     d += fabs(v);
212   }
213   SetLabel(state);
214 }
215 BIONIC_BENCHMARK_WITH_ARG(BM_math_fabs_macro, "MATH_COMMON");
216 
BM_math_fabs(benchmark::State & state)217 static void BM_math_fabs(benchmark::State& state) {
218   d = 0.0;
219   v = values[state.range(0)];
220   while (state.KeepRunning()) {
221     d += (fabs)(v);
222   }
223   SetLabel(state);
224 }
225 BIONIC_BENCHMARK_WITH_ARG(BM_math_fabs, "MATH_COMMON");
226 
BM_math_sincos(benchmark::State & state)227 static void BM_math_sincos(benchmark::State& state) {
228   d = 1.0;
229   while (state.KeepRunning()) {
230     double s, c;
231     sincos(d, &s, &c);
232     d += s + c;
233   }
234 }
235 BIONIC_BENCHMARK(BM_math_sincos);
236 
237 #include "expf_input.cpp"
238 
BM_math_expf_speccpu2017(benchmark::State & state)239 static void BM_math_expf_speccpu2017(benchmark::State& state) {
240   f = 0.0;
241   auto cin = expf_input.cbegin();
242   for (auto _ : state) {
243     f = expf(*cin);
244     if (++cin == expf_input.cend())
245       cin = expf_input.cbegin();
246   }
247 }
248 BIONIC_BENCHMARK(BM_math_expf_speccpu2017);
249 
BM_math_expf_speccpu2017_latency(benchmark::State & state)250 static void BM_math_expf_speccpu2017_latency(benchmark::State& state) {
251   f = 0.0;
252   auto cin = expf_input.cbegin();
253   for (auto _ : state) {
254     f = expf(f * zero + *cin);
255     if (++cin == expf_input.cend())
256       cin = expf_input.cbegin();
257   }
258 }
259 BIONIC_BENCHMARK(BM_math_expf_speccpu2017_latency);
260 
261 // Create a double version of expf_input to avoid overhead of float to
262 // double conversion.
263 static const std::vector<double> exp_input (expf_input.begin(),
264                                             expf_input.end());
265 
BM_math_exp_speccpu2017(benchmark::State & state)266 static void BM_math_exp_speccpu2017(benchmark::State& state) {
267   d = 0.0;
268   auto cin = exp_input.cbegin();
269   for (auto _ : state) {
270     d = exp(*cin);
271     if (++cin == exp_input.cend())
272       cin = exp_input.cbegin();
273   }
274 }
275 BIONIC_BENCHMARK(BM_math_exp_speccpu2017);
276 
BM_math_exp_speccpu2017_latency(benchmark::State & state)277 static void BM_math_exp_speccpu2017_latency(benchmark::State& state) {
278   d = 0.0;
279   auto cin = exp_input.cbegin();
280   for (auto _ : state) {
281     d = exp(d * zerod + *cin);
282     if (++cin == exp_input.cend())
283       cin = exp_input.cbegin();
284   }
285 }
286 BIONIC_BENCHMARK(BM_math_exp_speccpu2017_latency);
287 
BM_math_exp2f_speccpu2017(benchmark::State & state)288 static void BM_math_exp2f_speccpu2017(benchmark::State& state) {
289   f = 0.0;
290   auto cin = expf_input.cbegin();
291   for (auto _ : state) {
292     f = exp2f(*cin);
293     if (++cin == expf_input.cend())
294       cin = expf_input.cbegin();
295   }
296 }
297 BIONIC_BENCHMARK(BM_math_exp2f_speccpu2017);
298 
BM_math_exp2f_speccpu2017_latency(benchmark::State & state)299 static void BM_math_exp2f_speccpu2017_latency(benchmark::State& state) {
300   f = 0.0;
301   auto cin = expf_input.cbegin();
302   for (auto _ : state) {
303     f = exp2f(f * zero + *cin);
304     if (++cin == expf_input.cend())
305       cin = expf_input.cbegin();
306   }
307 }
308 BIONIC_BENCHMARK(BM_math_exp2f_speccpu2017_latency);
309 
BM_math_exp2_speccpu2017(benchmark::State & state)310 static void BM_math_exp2_speccpu2017(benchmark::State& state) {
311   d = 0.0;
312   auto cin = exp_input.cbegin();
313   for (auto _ : state) {
314     f = exp2(*cin);
315     if (++cin == exp_input.cend())
316       cin = exp_input.cbegin();
317   }
318 }
319 BIONIC_BENCHMARK(BM_math_exp2_speccpu2017);
320 
BM_math_exp2_speccpu2017_latency(benchmark::State & state)321 static void BM_math_exp2_speccpu2017_latency(benchmark::State& state) {
322   d = 0.0;
323   auto cin = exp_input.cbegin();
324   for (auto _ : state) {
325     f = exp2(d * zero + *cin);
326     if (++cin == exp_input.cend())
327       cin = exp_input.cbegin();
328   }
329 }
330 BIONIC_BENCHMARK(BM_math_exp2_speccpu2017_latency);
331 
332 #include "powf_input.cpp"
333 
334 static const std::vector<std::pair<double, double>> pow_input
335   (powf_input.begin(), powf_input.end());
336 
BM_math_powf_speccpu2006(benchmark::State & state)337 static void BM_math_powf_speccpu2006(benchmark::State& state) {
338   f = 0.0;
339   auto cin = powf_input.cbegin();
340   for (auto _ : state) {
341     f = powf(cin->first, cin->second);
342     if (++cin == powf_input.cend())
343       cin = powf_input.cbegin();
344   }
345 }
346 BIONIC_BENCHMARK(BM_math_powf_speccpu2006);
347 
BM_math_powf_speccpu2017_latency(benchmark::State & state)348 static void BM_math_powf_speccpu2017_latency(benchmark::State& state) {
349   f = 0.0;
350   auto cin = powf_input.cbegin();
351   for (auto _ : state) {
352     f = powf(f * zero + cin->first, cin->second);
353     if (++cin == powf_input.cend())
354       cin = powf_input.cbegin();
355   }
356 }
357 BIONIC_BENCHMARK(BM_math_powf_speccpu2017_latency);
358 
BM_math_pow_speccpu2006(benchmark::State & state)359 static void BM_math_pow_speccpu2006(benchmark::State& state) {
360   d = 0.0;
361   auto cin = pow_input.cbegin();
362   for (auto _ : state) {
363     f = pow(cin->first, cin->second);
364     if (++cin == pow_input.cend())
365       cin = pow_input.cbegin();
366   }
367 }
368 BIONIC_BENCHMARK(BM_math_pow_speccpu2006);
369 
BM_math_pow_speccpu2017_latency(benchmark::State & state)370 static void BM_math_pow_speccpu2017_latency(benchmark::State& state) {
371   d = 0.0;
372   auto cin = pow_input.cbegin();
373   for (auto _ : state) {
374     d = powf(d * zero + cin->first, cin->second);
375     if (++cin == pow_input.cend())
376       cin = pow_input.cbegin();
377   }
378 }
379 BIONIC_BENCHMARK(BM_math_pow_speccpu2017_latency);
380 
381 #include "logf_input.cpp"
382 
383 static const std::vector<double> log_input (logf_input.begin(),
384                                             logf_input.end());
385 
BM_math_logf_speccpu2017(benchmark::State & state)386 static void BM_math_logf_speccpu2017(benchmark::State& state) {
387   f = 0.0;
388   auto cin = logf_input.cbegin();
389   for (auto _ : state) {
390     f = logf(*cin);
391     if (++cin == logf_input.cend())
392       cin = logf_input.cbegin();
393   }
394 }
395 BIONIC_BENCHMARK(BM_math_logf_speccpu2017);
396 
BM_math_logf_speccpu2017_latency(benchmark::State & state)397 static void BM_math_logf_speccpu2017_latency(benchmark::State& state) {
398   f = 0.0;
399   auto cin = logf_input.cbegin();
400   for (auto _ : state) {
401     f = logf(f * zero + *cin);
402     if (++cin == logf_input.cend())
403       cin = logf_input.cbegin();
404   }
405 }
406 BIONIC_BENCHMARK(BM_math_logf_speccpu2017_latency);
407 
BM_math_log_speccpu2017(benchmark::State & state)408 static void BM_math_log_speccpu2017(benchmark::State& state) {
409   d = 0.0;
410   auto cin = log_input.cbegin();
411   for (auto _ : state) {
412     d = log(*cin);
413     if (++cin == log_input.cend())
414       cin = log_input.cbegin();
415   }
416 }
417 BIONIC_BENCHMARK(BM_math_log_speccpu2017);
418 
BM_math_log_speccpu2017_latency(benchmark::State & state)419 static void BM_math_log_speccpu2017_latency(benchmark::State& state) {
420   d = 0.0;
421   auto cin = log_input.cbegin();
422   for (auto _ : state) {
423     d = log(d * zerod + *cin);
424     if (++cin == log_input.cend())
425       cin = log_input.cbegin();
426   }
427 }
428 BIONIC_BENCHMARK(BM_math_log_speccpu2017_latency);
429 
BM_math_log2f_speccpu2017(benchmark::State & state)430 static void BM_math_log2f_speccpu2017(benchmark::State& state) {
431   f = 0.0;
432   auto cin = logf_input.cbegin();
433   for (auto _ : state) {
434     f = log2f(*cin);
435     if (++cin == logf_input.cend())
436       cin = logf_input.cbegin();
437   }
438 }
439 BIONIC_BENCHMARK(BM_math_log2f_speccpu2017);
440 
BM_math_log2_speccpu2017_latency(benchmark::State & state)441 static void BM_math_log2_speccpu2017_latency(benchmark::State& state) {
442   d = 0.0;
443   auto cin = log_input.cbegin();
444   for (auto _ : state) {
445     d = log2(d * zerod + *cin);
446     if (++cin == log_input.cend())
447       cin = log_input.cbegin();
448   }
449 }
450 BIONIC_BENCHMARK(BM_math_log2_speccpu2017_latency);
451 
BM_math_log2_speccpu2017(benchmark::State & state)452 static void BM_math_log2_speccpu2017(benchmark::State& state) {
453   d = 0.0;
454   auto cin = log_input.cbegin();
455   for (auto _ : state) {
456     d = log2(*cin);
457     if (++cin == log_input.cend())
458       cin = log_input.cbegin();
459   }
460 }
461 BIONIC_BENCHMARK(BM_math_log2_speccpu2017);
462 
BM_math_log2f_speccpu2017_latency(benchmark::State & state)463 static void BM_math_log2f_speccpu2017_latency(benchmark::State& state) {
464   f = 0.0;
465   auto cin = logf_input.cbegin();
466   for (auto _ : state) {
467     f = log2f(f * zero + *cin);
468     if (++cin == logf_input.cend())
469       cin = logf_input.cbegin();
470   }
471 }
472 BIONIC_BENCHMARK(BM_math_log2f_speccpu2017_latency);
473 
474 // Four ranges of values are checked:
475 // * 0.0 <= x < 0.1
476 // * 0.1 <= x < 0.7
477 // * 0.7 <= x < 3.1
478 // * -3.1 <= x < 3.1
479 // * 3.3 <= x < 33.3
480 // * 100.0 <= x < 1000.0
481 // * 1e6 <= x < 1e32
482 // * 1e32 < x < FLT_MAX
483 
484 #include "sincosf_input.cpp"
485 
BM_math_sinf(benchmark::State & state)486 static void BM_math_sinf(benchmark::State& state) {
487   auto range = sincosf_input[state.range(0)];
488   auto cin = range.values.cbegin();
489   f = 0.0;
490   for (auto _ : state) {
491     f = sinf(*cin);
492     if (++cin == range.values.cend())
493       cin = range.values.cbegin();
494   }
495   state.SetLabel(range.label);
496 }
497 BIONIC_BENCHMARK_WITH_ARG(BM_math_sinf, "MATH_SINCOS_COMMON");
498 
BM_math_sinf_latency(benchmark::State & state)499 static void BM_math_sinf_latency(benchmark::State& state) {
500   auto range = sincosf_input[state.range(0)];
501   auto cin = range.values.cbegin();
502   f = 0.0;
503   for (auto _ : state) {
504     f = sinf(f * zero + *cin);
505     if (++cin == range.values.cend())
506       cin = range.values.cbegin();
507   }
508   state.SetLabel(range.label);
509 }
510 BIONIC_BENCHMARK_WITH_ARG(BM_math_sinf_latency, "MATH_SINCOS_COMMON");
511 
BM_math_cosf(benchmark::State & state)512 static void BM_math_cosf(benchmark::State& state) {
513   auto range = sincosf_input[state.range(0)];
514   auto cin = range.values.cbegin();
515   f = 0.0;
516   for (auto _ : state) {
517     f = cosf(*cin);
518     if (++cin == range.values.cend())
519       cin = range.values.cbegin();
520   }
521   state.SetLabel(range.label);
522 }
523 BIONIC_BENCHMARK_WITH_ARG(BM_math_cosf, "MATH_SINCOS_COMMON");
524 
BM_math_cosf_latency(benchmark::State & state)525 static void BM_math_cosf_latency(benchmark::State& state) {
526   auto range = sincosf_input[state.range(0)];
527   auto cin = range.values.cbegin();
528   f = 0.0;
529   for (auto _ : state) {
530     f = cosf(f * zero + *cin);
531     if (++cin == range.values.cend())
532       cin = range.values.cbegin();
533   }
534   state.SetLabel(range.label);
535 }
536 BIONIC_BENCHMARK_WITH_ARG(BM_math_cosf_latency, "MATH_SINCOS_COMMON");
537 
BM_math_sincosf(benchmark::State & state)538 static void BM_math_sincosf(benchmark::State& state) {
539   auto range = sincosf_input[state.range(0)];
540   auto cin = range.values.cbegin();
541   f = 0.0;
542   for (auto _ : state) {
543     float s, c;
544     sincosf(*cin, &s, &c);
545     f += s;
546     if (++cin == range.values.cend())
547       cin = range.values.cbegin();
548   }
549   state.SetLabel(range.label);
550 }
551 BIONIC_BENCHMARK_WITH_ARG(BM_math_sincosf, "MATH_SINCOS_COMMON");
552 
BM_math_sincosf_latency(benchmark::State & state)553 static void BM_math_sincosf_latency(benchmark::State& state) {
554   auto range = sincosf_input[state.range(0)];
555   auto cin = range.values.cbegin();
556   f = 0.0;
557   for (auto _ : state) {
558     float s, c;
559     sincosf(f * zero + *cin, &s, &c);
560     f += s;
561     if (++cin == range.values.cend())
562       cin = range.values.cbegin();
563   }
564   state.SetLabel(range.label);
565 }
566 BIONIC_BENCHMARK_WITH_ARG(BM_math_sincosf_latency, "MATH_SINCOS_COMMON");
567