[go: nahoru, domu]

Skip to content

Commit

Permalink
Compare performance to NEON-FP16 on ARM
Browse files Browse the repository at this point in the history
  • Loading branch information
Maratyszcza committed Mar 23, 2017
1 parent 4b29617 commit 5d73573
Show file tree
Hide file tree
Showing 4 changed files with 194 additions and 0 deletions.
49 changes: 49 additions & 0 deletions bench/from-alt-array.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
#include <functional>
#include <algorithm>

#if defined(__ARM_NEON__) || defined(__aarch64__)
#include <arm_neon.h>
#endif


static void fp16_alt_to_fp32_bits(benchmark::State& state) {
const uint_fast32_t seed = std::chrono::system_clock::now().time_since_epoch().count();
Expand Down Expand Up @@ -123,4 +127,49 @@ BENCHMARK(fp16_alt_to_fp32_value)->RangeMultiplier(2)->Range(1<<10, 64<<20);
BENCHMARK(fp16_alt_to_fp32x2_psimd)->RangeMultiplier(2)->Range(1<<10, 64<<20);
#endif

#if defined(__ARM_NEON_FP) && (__ARM_NEON_FP & 0x2) || defined(__aarch64__)
static void hardware_vcvt_f32_f16(benchmark::State& state) {
const uint_fast32_t seed = std::chrono::system_clock::now().time_since_epoch().count();
auto rng = std::bind(std::uniform_real_distribution<float>(-1.0f, 1.0f), std::mt19937(seed));

std::vector<uint16_t> fp16(state.range(0));
std::vector<float> fp32(state.range(0));
std::generate(fp16.begin(), fp16.end(),
[&rng]{ return fp16_ieee_from_fp32_value(rng()); });

while (state.KeepRunning()) {
uint16_t* input = fp16.data();
benchmark::DoNotOptimize(input);

float* output = fp32.data();
const size_t n = state.range(0);
#if defined(__aarch64__)
const unsigned int fpcr = __builtin_aarch64_get_fpcr();
/* Disable flush-to-zero (bit 24) and enable Alternative FP16 format (bit 26) */
__builtin_aarch64_set_fpcr((fpcr & 0xFEFFFFFFu) | 0x08000000u);
#else
unsigned int fpscr;
__asm__ __volatile__ ("VMRS %[fpscr], fpscr" : [fpscr] "=r" (fpscr));
/* Disable flush-to-zero (bit 24) and enable Alternative FP16 format (bit 26) */
__asm__ __volatile__ ("VMSR fpscr, %[fpscr]" :
: [fpscr] "r" ((fpscr & 0xFEFFFFFFu) | 0x08000000u));
#endif
for (size_t i = 0; i < n; i += 4) {
vst1q_f32(&output[i],
vcvt_f32_f16(
(float16x4_t) vld1_u16(&input[i])));
}
#if defined(__aarch64__)
__builtin_aarch64_set_fpcr(fpcr);
#else
__asm__ __volatile__ ("VMSR fpscr, %[fpscr]" :: [fpscr] "r" (fpscr));
#endif

benchmark::DoNotOptimize(output);
}
state.SetItemsProcessed(int64_t(state.iterations()) * int64_t(state.range(0)));
}
BENCHMARK(hardware_vcvt_f32_f16)->RangeMultiplier(2)->Range(1<<10, 64<<20);
#endif

BENCHMARK_MAIN();
49 changes: 49 additions & 0 deletions bench/from-ieee-array.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
#include <immintrin.h>
#endif

#if defined(__ARM_NEON__) || defined(__aarch64__)
#include <arm_neon.h>
#endif

#ifdef FP16_COMPARATIVE_BENCHMARKS
#include <third-party/THHalf.h>
#include <third-party/npy-halffloat.h>
Expand Down Expand Up @@ -191,6 +195,51 @@ BENCHMARK(fp16_ieee_to_fp32_value)->RangeMultiplier(2)->Range(1<<10, 64<<20);
BENCHMARK(hardware_mm256_cvtph_ps)->RangeMultiplier(2)->Range(1<<10, 64<<20);
#endif

#if defined(__ARM_NEON_FP) && (__ARM_NEON_FP & 0x2) || defined(__aarch64__)
static void hardware_vcvt_f32_f16(benchmark::State& state) {
const uint_fast32_t seed = std::chrono::system_clock::now().time_since_epoch().count();
auto rng = std::bind(std::uniform_real_distribution<float>(-1.0f, 1.0f), std::mt19937(seed));

std::vector<uint16_t> fp16(state.range(0));
std::vector<float> fp32(state.range(0));
std::generate(fp16.begin(), fp16.end(),
[&rng]{ return fp16_ieee_from_fp32_value(rng()); });

while (state.KeepRunning()) {
uint16_t* input = fp16.data();
benchmark::DoNotOptimize(input);

float* output = fp32.data();
const size_t n = state.range(0);
#if defined(__aarch64__)
const unsigned int fpcr = __builtin_aarch64_get_fpcr();
/* Disable flush-to-zero (bit 24) and Alternative FP16 format (bit 26) */
__builtin_aarch64_set_fpcr(fpcr & 0xF6FFFFFFu);
#else
unsigned int fpscr;
__asm__ __volatile__ ("VMRS %[fpscr], fpscr" : [fpscr] "=r" (fpscr));
/* Disable flush-to-zero (bit 24) and Alternative FP16 format (bit 26) */
__asm__ __volatile__ ("VMSR fpscr, %[fpscr]" :
: [fpscr] "r" (fpscr & 0xF6FFFFFFu));
#endif
for (size_t i = 0; i < n; i += 4) {
vst1q_f32(&output[i],
vcvt_f32_f16(
(float16x4_t) vld1_u16(&input[i])));
}
#if defined(__aarch64__)
__builtin_aarch64_set_fpcr(fpcr);
#else
__asm__ __volatile__ ("VMSR fpscr, %[fpscr]" :: [fpscr] "r" (fpscr));
#endif

benchmark::DoNotOptimize(output);
}
state.SetItemsProcessed(int64_t(state.iterations()) * int64_t(state.range(0)));
}
BENCHMARK(hardware_vcvt_f32_f16)->RangeMultiplier(2)->Range(1<<10, 64<<20);
#endif

#ifdef FP16_COMPARATIVE_BENCHMARKS
static void TH_halfbits2float(benchmark::State& state) {
const uint_fast32_t seed = std::chrono::system_clock::now().time_since_epoch().count();
Expand Down
48 changes: 48 additions & 0 deletions bench/to-alt-array.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
#include <immintrin.h>
#endif

#if defined(__ARM_NEON__) || defined(__aarch64__)
#include <arm_neon.h>
#endif


static void fp16_alt_from_fp32_value(benchmark::State& state) {
const uint_fast32_t seed = std::chrono::system_clock::now().time_since_epoch().count();
Expand All @@ -40,4 +44,48 @@ static void fp16_alt_from_fp32_value(benchmark::State& state) {
}
BENCHMARK(fp16_alt_from_fp32_value)->RangeMultiplier(2)->Range(1<<10, 64<<20);

#if defined(__ARM_NEON_FP) && (__ARM_NEON_FP & 0x2) || defined(__aarch64__)
static void hardware_vcvt_f16_f32(benchmark::State& state) {
const uint_fast32_t seed = std::chrono::system_clock::now().time_since_epoch().count();
auto rng = std::bind(std::uniform_real_distribution<float>(-1.0f, 1.0f), std::mt19937(seed));

std::vector<float> fp32(state.range(0));
std::vector<uint16_t> fp16(state.range(0));
std::generate(fp32.begin(), fp32.end(), std::ref(rng));

while (state.KeepRunning()) {
float* input = fp32.data();
benchmark::DoNotOptimize(input);

uint16_t* output = fp16.data();
const size_t n = state.range(0);
#if defined(__aarch64__)
const unsigned int fpcr = __builtin_aarch64_get_fpcr();
/* Disable flush-to-zero (bit 24) and enable Alternative FP16 format (bit 26) */
__builtin_aarch64_set_fpcr((fpcr & 0xFEFFFFFFu) | 0x08000000u);
#else
unsigned int fpscr;
__asm__ __volatile__ ("VMRS %[fpscr], fpscr" : [fpscr] "=r" (fpscr));
/* Disable flush-to-zero (bit 24) and enable Alternative FP16 format (bit 26) */
__asm__ __volatile__ ("VMSR fpscr, %[fpscr]" :
: [fpscr] "r" ((fpscr & 0xFEFFFFFFu) | 0x08000000u));
#endif
for (size_t i = 0; i < n; i += 4) {
vst1_u16(&output[i],
(uint16x4_t) vcvt_f16_f32(
vld1q_f32(&input[i])));
}
#if defined(__aarch64__)
__builtin_aarch64_set_fpcr(fpcr);
#else
__asm__ __volatile__ ("VMSR fpscr, %[fpscr]" :: [fpscr] "r" (fpscr));
#endif

benchmark::DoNotOptimize(output);
}
state.SetItemsProcessed(int64_t(state.iterations()) * int64_t(state.range(0)));
}
BENCHMARK(hardware_vcvt_f16_f32)->RangeMultiplier(2)->Range(1<<10, 64<<20);
#endif

BENCHMARK_MAIN();
48 changes: 48 additions & 0 deletions bench/to-ieee-array.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
#include <immintrin.h>
#endif

#if defined(__ARM_NEON__) || defined(__aarch64__)
#include <arm_neon.h>
#endif

#ifdef FP16_COMPARATIVE_BENCHMARKS
#include <third-party/THHalf.h>
#include <third-party/npy-halffloat.h>
Expand Down Expand Up @@ -102,6 +106,50 @@ BENCHMARK(fp16_ieee_from_fp32_value)->RangeMultiplier(2)->Range(1<<10, 64<<20);
BENCHMARK(hardware_mm256_cvtps_ph)->RangeMultiplier(2)->Range(1<<10, 64<<20);
#endif

#if defined(__ARM_NEON_FP) && (__ARM_NEON_FP & 0x2) || defined(__aarch64__)
static void hardware_vcvt_f16_f32(benchmark::State& state) {
const uint_fast32_t seed = std::chrono::system_clock::now().time_since_epoch().count();
auto rng = std::bind(std::uniform_real_distribution<float>(-1.0f, 1.0f), std::mt19937(seed));

std::vector<float> fp32(state.range(0));
std::vector<uint16_t> fp16(state.range(0));
std::generate(fp32.begin(), fp32.end(), std::ref(rng));

while (state.KeepRunning()) {
float* input = fp32.data();
benchmark::DoNotOptimize(input);

uint16_t* output = fp16.data();
const size_t n = state.range(0);
#if defined(__aarch64__)
const unsigned int fpcr = __builtin_aarch64_get_fpcr();
/* Disable flush-to-zero (bit 24) and Alternative FP16 format (bit 26) */
__builtin_aarch64_set_fpcr(fpcr & 0xF6FFFFFFu);
#else
unsigned int fpscr;
__asm__ __volatile__ ("VMRS %[fpscr], fpscr" : [fpscr] "=r" (fpscr));
/* Disable flush-to-zero (bit 24) and Alternative FP16 format (bit 26) */
__asm__ __volatile__ ("VMSR fpscr, %[fpscr]" :
: [fpscr] "r" (fpscr & 0xF6FFFFFFu));
#endif
for (size_t i = 0; i < n; i += 4) {
vst1_u16(&output[i],
(uint16x4_t) vcvt_f16_f32(
vld1q_f32(&input[i])));
}
#if defined(__aarch64__)
__builtin_aarch64_set_fpcr(fpcr);
#else
__asm__ __volatile__ ("VMSR fpscr, %[fpscr]" :: [fpscr] "r" (fpscr));
#endif

benchmark::DoNotOptimize(output);
}
state.SetItemsProcessed(int64_t(state.iterations()) * int64_t(state.range(0)));
}
BENCHMARK(hardware_vcvt_f16_f32)->RangeMultiplier(2)->Range(1<<10, 64<<20);
#endif

#ifdef FP16_COMPARATIVE_BENCHMARKS
static void TH_float2halfbits(benchmark::State& state) {
const uint_fast32_t seed = std::chrono::system_clock::now().time_since_epoch().count();
Expand Down

0 comments on commit 5d73573

Please sign in to comment.