blob: 5738b304403489f1cffbca76b8e543f2158d1895 [file]
// SPDX-FileCopyrightText: The Eigen Authors
// SPDX-License-Identifier: MPL-2.0
#include <benchmark/benchmark.h>
#include <Eigen/Core>
#include <cstdint>
#ifndef EIGEN_BENCH_ASSIGN_SCALAR
#define EIGEN_BENCH_ASSIGN_SCALAR double
#endif
#ifndef EIGEN_BENCH_ASSIGN_OP
// 0: abs, 1: square, 2: add, 3: copy, 4: exp.
#define EIGEN_BENCH_ASSIGN_OP 0
#endif
using namespace Eigen;
static void BM_Assignment(benchmark::State& state) {
using Scalar = EIGEN_BENCH_ASSIGN_SCALAR;
using Vector = Array<Scalar, Dynamic, 1>;
// Control the low address bits independently: matching page offsets can trigger false store/load dependencies.
constexpr Index pageSize = 4096;
const Index size = state.range(0);
Vector storage(3 * size + 3 * pageSize / sizeof(Scalar));
Scalar* source = storage.data() + internal::first_aligned<pageSize>(storage.data(), storage.size());
const Index separation = (((size + 1) * sizeof(Scalar) + pageSize - 1) / pageSize) * pageSize / sizeof(Scalar);
Map<Vector> input(source + state.range(1), size);
Map<Vector> output(source + separation + state.range(2), size);
Vector other(size);
for (Index i = 0; i < size; ++i) {
input(i) = Scalar(i % 127 - 63) / Scalar(32);
other(i) = Scalar(i % 61 - 30) / Scalar(16);
}
for (auto _ : state) {
benchmark::DoNotOptimize(input.data());
benchmark::DoNotOptimize(other.data());
#if EIGEN_BENCH_ASSIGN_OP == 0
output = input.abs();
#elif EIGEN_BENCH_ASSIGN_OP == 1
output = input.square();
#elif EIGEN_BENCH_ASSIGN_OP == 2
output = input + other;
#elif EIGEN_BENCH_ASSIGN_OP == 3
output = input;
#else
output = input.exp();
#endif
benchmark::DoNotOptimize(output.data());
benchmark::ClobberMemory();
}
for (Index i = 0; i < size; ++i) {
#if EIGEN_BENCH_ASSIGN_OP == 0
const Scalar expected = numext::abs(input(i));
#elif EIGEN_BENCH_ASSIGN_OP == 1
const Scalar expected = input(i) * input(i);
#elif EIGEN_BENCH_ASSIGN_OP == 2
const Scalar expected = input(i) + other(i);
#elif EIGEN_BENCH_ASSIGN_OP == 3
const Scalar expected = input(i);
#else
const Scalar expected = numext::exp(input(i));
#endif
if (!(numext::abs(output(i) - expected) <= Scalar(8) * NumTraits<Scalar>::epsilon() * numext::abs(expected))) {
state.SkipWithError("assignment differs from the scalar reference");
return;
}
}
state.SetBytesProcessed(state.iterations() * size * sizeof(Scalar) * (EIGEN_BENCH_ASSIGN_OP == 2 ? 3 : 2));
}
BENCHMARK(BM_Assignment)
->ArgsProduct({{31, 32, 33, 127, 128, 129, 255, 256, 257, 1023, 1024, 1025, 4095, 4096, 4097, 16384, 65536,
1048576},
{0, 1},
{0, 16}});