blob: 8ef4f1916bc7d560ba34ef82b378f42837255a5d [file] [log] [blame]
Marat Dukhan1718dae2017-02-17 22:41:54 -05001#include <benchmark/benchmark.h>
2
3#include <fp16.h>
4#ifndef EMSCRIPTEN
5 #include <fp16/psimd.h>
6#endif
7
8#include <vector>
9#include <random>
10#include <chrono>
11#include <functional>
12#include <algorithm>
13
14#if (defined(__i386__) || defined(__x86_64__)) && defined(__F16C__)
15 #include <immintrin.h>
16#endif
17
Marat Dukhan5d735732017-03-23 14:33:37 +000018#if defined(__ARM_NEON__) || defined(__aarch64__)
19 #include <arm_neon.h>
20#endif
21
Marat Dukhan1718dae2017-02-17 22:41:54 -050022
23static void fp16_alt_from_fp32_value(benchmark::State& state) {
24 const uint_fast32_t seed = std::chrono::system_clock::now().time_since_epoch().count();
25 auto rng = std::bind(std::uniform_real_distribution<float>(-1.0f, 1.0f), std::mt19937(seed));
26
27 std::vector<float> fp32(state.range(0));
28 std::vector<uint16_t> fp16(state.range(0));
29 std::generate(fp32.begin(), fp32.end(), std::ref(rng));
30
31 while (state.KeepRunning()) {
32 float* input = fp32.data();
33 benchmark::DoNotOptimize(input);
34
35 uint16_t* output = fp16.data();
36 const size_t n = state.range(0);
37 for (size_t i = 0; i < n; i++) {
38 output[i] = fp16_alt_from_fp32_value(input[i]);
39 }
40
41 benchmark::DoNotOptimize(output);
42 }
43 state.SetItemsProcessed(int64_t(state.iterations()) * int64_t(state.range(0)));
44}
45BENCHMARK(fp16_alt_from_fp32_value)->RangeMultiplier(2)->Range(1<<10, 64<<20);
46
Marat Dukhan5d735732017-03-23 14:33:37 +000047#if defined(__ARM_NEON_FP) && (__ARM_NEON_FP & 0x2) || defined(__aarch64__)
48 static void hardware_vcvt_f16_f32(benchmark::State& state) {
49 const uint_fast32_t seed = std::chrono::system_clock::now().time_since_epoch().count();
50 auto rng = std::bind(std::uniform_real_distribution<float>(-1.0f, 1.0f), std::mt19937(seed));
51
52 std::vector<float> fp32(state.range(0));
53 std::vector<uint16_t> fp16(state.range(0));
54 std::generate(fp32.begin(), fp32.end(), std::ref(rng));
55
56 while (state.KeepRunning()) {
57 float* input = fp32.data();
58 benchmark::DoNotOptimize(input);
59
60 uint16_t* output = fp16.data();
61 const size_t n = state.range(0);
62 #if defined(__aarch64__)
63 const unsigned int fpcr = __builtin_aarch64_get_fpcr();
64 /* Disable flush-to-zero (bit 24) and enable Alternative FP16 format (bit 26) */
65 __builtin_aarch64_set_fpcr((fpcr & 0xFEFFFFFFu) | 0x08000000u);
66 #else
67 unsigned int fpscr;
68 __asm__ __volatile__ ("VMRS %[fpscr], fpscr" : [fpscr] "=r" (fpscr));
69 /* Disable flush-to-zero (bit 24) and enable Alternative FP16 format (bit 26) */
70 __asm__ __volatile__ ("VMSR fpscr, %[fpscr]" :
71 : [fpscr] "r" ((fpscr & 0xFEFFFFFFu) | 0x08000000u));
72 #endif
73 for (size_t i = 0; i < n; i += 4) {
74 vst1_u16(&output[i],
75 (uint16x4_t) vcvt_f16_f32(
76 vld1q_f32(&input[i])));
77 }
78 #if defined(__aarch64__)
79 __builtin_aarch64_set_fpcr(fpcr);
80 #else
81 __asm__ __volatile__ ("VMSR fpscr, %[fpscr]" :: [fpscr] "r" (fpscr));
82 #endif
83
84 benchmark::DoNotOptimize(output);
85 }
86 state.SetItemsProcessed(int64_t(state.iterations()) * int64_t(state.range(0)));
87 }
88 BENCHMARK(hardware_vcvt_f16_f32)->RangeMultiplier(2)->Range(1<<10, 64<<20);
89#endif
90
Marat Dukhan1718dae2017-02-17 22:41:54 -050091BENCHMARK_MAIN();