blob: 06469b0fb2d68d34dd12eb1f3b51c9464118cfd2 [file]
// SPDX-FileCopyrightText: The Eigen Authors
// SPDX-License-Identifier: MPL-2.0
#include <benchmark/benchmark.h>
#include <contrib/Eigen/Tensor>
using Eigen::Index;
using Eigen::internal::TiledEvaluation;
template <typename Scalar, int Layout, bool Shuffle>
static void BM_BlockView(benchmark::State& state) {
const Index n = state.range(0);
const bool tiled = state.range(1) != 0;
using Tensor = Eigen::Tensor<Scalar, 2, Layout>;
Tensor input(n, n), bias(n, n), output(n, n);
for (Index j = 0; j < n; ++j) {
for (Index i = 0; i < n; ++i) {
input(i, j) = Scalar((i * 17 + j * 31) % 1024) * Scalar(0.25);
bias(i, j) = Scalar((i * 7 + j * 11) % 256) * Scalar(0.125);
}
}
auto measure = [&](const auto& expression) {
using Expression = Eigen::internal::remove_all_t<decltype(expression)>;
using Assign = Eigen::TensorAssignOp<Tensor, const Expression>;
using Device = Eigen::DefaultDevice;
constexpr bool Vectorizable = Eigen::internal::IsVectorizable<Device, const Assign>::value;
using Tiled = Eigen::internal::TensorExecutor<const Assign, Device, Vectorizable, TiledEvaluation::On>;
using Untiled = Eigen::internal::TensorExecutor<const Assign, Device, Vectorizable, TiledEvaluation::Off>;
const Assign assign(output, expression);
if (tiled) {
Tiled::run(assign);
} else {
Untiled::run(assign);
}
for (Index j = 0; j < n; ++j) {
for (Index i = 0; i < n; ++i) {
const Scalar expected = (Shuffle ? input(j, i) : input(i, j)) + bias(i, j);
if (output(i, j) != expected) {
state.SkipWithError("incorrect block result");
return;
}
}
}
if (tiled) {
for (auto unused : state) {
Tiled::run(assign);
benchmark::DoNotOptimize(output.data());
benchmark::ClobberMemory();
}
} else {
for (auto unused : state) {
Untiled::run(assign);
benchmark::DoNotOptimize(output.data());
benchmark::ClobberMemory();
}
}
};
EIGEN_IF_CONSTEXPR (Shuffle) {
const Eigen::array<int, 2> transpose{{1, 0}};
measure(input.shuffle(transpose) + bias);
} else {
// Identity broadcasting selects contiguous blocks for the control case.
const Eigen::array<Index, 2> broadcast{{1, 1}};
measure(input.broadcast(broadcast) + bias);
}
state.SetItemsProcessed(state.iterations() * n * n);
}
#define REGISTER_BLOCK_VIEW(Scalar, Layout, Shuffle) \
BENCHMARK_TEMPLATE(BM_BlockView, Scalar, Layout, Shuffle) \
->ArgsProduct({{64, 96, 112, 128, 192, 256, 257, 384, 512, 1024}, {0, 1}})
REGISTER_BLOCK_VIEW(float, Eigen::ColMajor, true);
REGISTER_BLOCK_VIEW(float, Eigen::RowMajor, true);
REGISTER_BLOCK_VIEW(double, Eigen::ColMajor, true);
REGISTER_BLOCK_VIEW(double, Eigen::RowMajor, true);
REGISTER_BLOCK_VIEW(float, Eigen::ColMajor, false);
REGISTER_BLOCK_VIEW(float, Eigen::RowMajor, false);
#undef REGISTER_BLOCK_VIEW