blob: 11d678be77ca6e53a67f86ff4419fb4916cd3cea [file] [edit]
// SPDX-FileCopyrightText: The Eigen Authors
// SPDX-License-Identifier: MPL-2.0
#include <benchmark/benchmark.h>
#include <Eigen/SVD>
#include <complex>
#include <cstdlib>
template <typename Scalar, int Options>
static void BM_JacobiSVDRotations(benchmark::State& state) {
using Matrix = Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>;
using RealScalar = typename Eigen::NumTraits<Scalar>::Real;
const Eigen::Index rows = state.range(0);
const Eigen::Index cols = state.range(1);
Matrix matrix(rows, cols);
std::srand(5489);
matrix.setRandom();
benchmark::DoNotOptimize(matrix.data());
benchmark::ClobberMemory();
Eigen::JacobiSVD<Matrix, Eigen::ComputeThinU | Eigen::ComputeThinV> reference(matrix);
const RealScalar tolerance = RealScalar(128 * rows) * Eigen::NumTraits<RealScalar>::epsilon();
const Matrix reconstructed =
reference.matrixU() * reference.singularValues().asDiagonal() * reference.matrixV().adjoint();
if (reference.info() != Eigen::Success || !((matrix - reconstructed).norm() <= tolerance * matrix.norm()) ||
!((reference.matrixU().adjoint() * reference.matrixU() - Matrix::Identity(cols, cols)).norm() <= tolerance) ||
!((reference.matrixV().adjoint() * reference.matrixV() - Matrix::Identity(cols, cols)).norm() <= tolerance)) {
state.SkipWithError("JacobiSVD failed reconstruction or unitarity check");
return;
}
Eigen::JacobiSVD<Matrix, Options> svd(rows, cols);
svd.compute(matrix);
if (svd.info() != Eigen::Success ||
!((svd.singularValues() - reference.singularValues()).norm() <= tolerance * matrix.norm())) {
state.SkipWithError("JacobiSVD failed singular-value check");
return;
}
for (auto _ : state) {
benchmark::ClobberMemory();
svd.compute(matrix);
benchmark::DoNotOptimize(svd.singularValues().data());
EIGEN_IF_CONSTEXPR (Options != 0) {
benchmark::DoNotOptimize(svd.matrixU().data());
benchmark::DoNotOptimize(svd.matrixV().data());
}
benchmark::ClobberMemory();
}
state.SetItemsProcessed(state.iterations());
}
#define JACOBI_ROTATION_SHAPES ->Args({3, 3})->Args({16, 16})->Args({64, 64})->Args({64, 16})
BENCHMARK_TEMPLATE(BM_JacobiSVDRotations, float, 0) JACOBI_ROTATION_SHAPES;
BENCHMARK_TEMPLATE(BM_JacobiSVDRotations, double, 0) JACOBI_ROTATION_SHAPES;
BENCHMARK_TEMPLATE(BM_JacobiSVDRotations, std::complex<float>, 0) JACOBI_ROTATION_SHAPES;
BENCHMARK_TEMPLATE(BM_JacobiSVDRotations, std::complex<double>, 0) JACOBI_ROTATION_SHAPES;
BENCHMARK_TEMPLATE(BM_JacobiSVDRotations, float, Eigen::ComputeThinU | Eigen::ComputeThinV) JACOBI_ROTATION_SHAPES;
BENCHMARK_TEMPLATE(BM_JacobiSVDRotations, double, Eigen::ComputeThinU | Eigen::ComputeThinV) JACOBI_ROTATION_SHAPES;
BENCHMARK_TEMPLATE(BM_JacobiSVDRotations, std::complex<float>, Eigen::ComputeThinU | Eigen::ComputeThinV)
JACOBI_ROTATION_SHAPES;
BENCHMARK_TEMPLATE(BM_JacobiSVDRotations, std::complex<double>, Eigen::ComputeThinU | Eigen::ComputeThinV)
JACOBI_ROTATION_SHAPES;
#undef JACOBI_ROTATION_SHAPES