| // Benchmarks for Eigen Spline module. | |
| // Tests fitting, evaluation, and derivative computation. | |
| // SPDX-FileCopyrightText: The Eigen Authors | |
| // SPDX-License-Identifier: MPL-2.0 | |
| #include <benchmark/benchmark.h> | |
| #include <Eigen/Core> | |
| #include <contrib/Eigen/Splines> | |
| using namespace Eigen; | |
| typedef double Scalar; | |
| // --- Spline fitting (interpolation) --- | |
| template <int Dim, int Degree> | |
| static void BM_SplineFit(benchmark::State& state) { | |
| const int n = state.range(0); | |
| typedef Spline<Scalar, Dim> SplineType; | |
| typedef typename SplineType::PointType PointType; | |
| // Generate random points. | |
| Matrix<Scalar, Dim, Dynamic> pts(Dim, n); | |
| pts.setRandom(); | |
| for (auto _ : state) { | |
| SplineType spline = SplineFitting<SplineType>::Interpolate(pts, Degree); | |
| benchmark::DoNotOptimize(spline.knots().data()); | |
| benchmark::ClobberMemory(); | |
| } | |
| } | |
| // --- Spline evaluation --- | |
| template <int Dim, int Degree> | |
| static void BM_SplineEval(benchmark::State& state) { | |
| const int n = state.range(0); // number of control points for fitting | |
| const int neval = 1000; // number of evaluation points | |
| typedef Spline<Scalar, Dim> SplineType; | |
| Matrix<Scalar, Dim, Dynamic> pts(Dim, n); | |
| pts.setRandom(); | |
| SplineType spline = SplineFitting<SplineType>::Interpolate(pts, Degree); | |
| // Generate evaluation parameters in [0, 1]. | |
| VectorXd u = VectorXd::LinSpaced(neval, 0, 1); | |
| for (auto _ : state) { | |
| for (int i = 0; i < neval; ++i) { | |
| auto pt = spline(u(i)); | |
| benchmark::DoNotOptimize(pt.data()); | |
| } | |
| benchmark::ClobberMemory(); | |
| } | |
| state.counters["Evals/s"] = benchmark::Counter(neval, benchmark::Counter::kIsIterationInvariantRate); | |
| } | |
| // --- Spline derivative evaluation --- | |
| template <int Dim, int Degree> | |
| static void BM_SplineDerivatives(benchmark::State& state) { | |
| const int n = state.range(0); | |
| const int neval = 1000; | |
| typedef Spline<Scalar, Dim> SplineType; | |
| Matrix<Scalar, Dim, Dynamic> pts(Dim, n); | |
| pts.setRandom(); | |
| SplineType spline = SplineFitting<SplineType>::Interpolate(pts, Degree); | |
| VectorXd u = VectorXd::LinSpaced(neval, 0, 1); | |
| for (auto _ : state) { | |
| for (int i = 0; i < neval; ++i) { | |
| auto derivs = spline.derivatives(u(i), 1); | |
| benchmark::DoNotOptimize(derivs.data()); | |
| } | |
| benchmark::ClobberMemory(); | |
| } | |
| state.counters["Evals/s"] = benchmark::Counter(neval, benchmark::Counter::kIsIterationInvariantRate); | |
| } | |
| #define SPLINE_SIZES ->Arg(10)->Arg(50)->Arg(200)->Arg(1000) | |
| // 2D cubic splines | |
| BENCHMARK(BM_SplineFit<2, 3>) SPLINE_SIZES->Name("SplineFit_2D_Cubic"); | |
| BENCHMARK(BM_SplineEval<2, 3>) SPLINE_SIZES->Name("SplineEval_2D_Cubic"); | |
| BENCHMARK(BM_SplineDerivatives<2, 3>) SPLINE_SIZES->Name("SplineDerivatives_2D_Cubic"); | |
| // 3D cubic splines | |
| BENCHMARK(BM_SplineFit<3, 3>) SPLINE_SIZES->Name("SplineFit_3D_Cubic"); | |
| BENCHMARK(BM_SplineEval<3, 3>) SPLINE_SIZES->Name("SplineEval_3D_Cubic"); | |
| BENCHMARK(BM_SplineDerivatives<3, 3>) SPLINE_SIZES->Name("SplineDerivatives_3D_Cubic"); | |
| // 2D quintic splines | |
| BENCHMARK(BM_SplineFit<2, 5>) SPLINE_SIZES->Name("SplineFit_2D_Quintic"); | |
| BENCHMARK(BM_SplineEval<2, 5>) SPLINE_SIZES->Name("SplineEval_2D_Quintic"); |