blob: 99a33eb9405e2edeabd50872ec2ae8a7a1994908 [file] [edit]
// Benchmarks for vectorized casts between integer and floating-point arrays.
// SPDX-FileCopyrightText: The Eigen Authors
// SPDX-License-Identifier: MPL-2.0
#include <benchmark/benchmark.h>
#include <Eigen/Core>
#include <cmath>
#include <cstdint>
#include <random>
#include <type_traits>
using namespace Eigen;
// 64-bit integers of every magnitude; about one in six is at least 2^53, where double cannot hold it exactly.
template <typename Src>
static void BM_CastToFloat(benchmark::State& state) {
const Index size = state.range(0);
Array<Src, Dynamic, 1> input(size);
std::mt19937_64 rng(42);
for (Index i = 0; i < size; ++i) {
const uint64_t bits = rng() >> (rng() % 64);
input(i) = static_cast<Src>(std::is_signed<Src>::value && (rng() & 1) ? uint64_t(0) - (bits >> 1) : bits);
}
ArrayXf output = input.template cast<float>();
for (Index i = 0; i < size; ++i) {
// Within an ulp: a conversion that rounds twice through double is off by at most one ulp.
const float expected = static_cast<float>(static_cast<double>(input(i)));
if (!(std::abs(output(i) - expected) <= std::abs(expected) * NumTraits<float>::epsilon())) {
state.SkipWithError("cast failed reference validation");
return;
}
}
for (auto _ : state) {
benchmark::DoNotOptimize(input.data());
output = input.template cast<float>();
benchmark::DoNotOptimize(output.data());
benchmark::ClobberMemory();
}
state.SetItemsProcessed(state.iterations() * size);
}
BENCHMARK_TEMPLATE(BM_CastToFloat, int64_t)->Arg(64)->Arg(4096)->Arg(262144);
BENCHMARK_TEMPLATE(BM_CastToFloat, uint64_t)->Arg(64)->Arg(4096)->Arg(262144);