From 2c820150a1276f9c52772f394af7141c164d0092 Mon Sep 17 00:00:00 2001 From: Joana Niermann Date: Wed, 17 Jul 2024 11:31:46 +0200 Subject: [PATCH] Add matrix benchmarks --- .github/workflows/checks.yml | 4 +- benchmarks/CMakeLists.txt | 16 + benchmarks/array/array_matrix.cpp | 99 ++++++ .../benchmark/array/data_generator.hpp | 34 +- .../benchmark/common/benchmark_base.hpp | 2 +- .../benchmark/common/benchmark_matrix.hpp | 190 ++++++++++++ .../benchmark/common/benchmark_transform3.hpp | 14 +- .../benchmark/common/benchmark_vector.hpp | 18 +- benchmarks/eigen/eigen_matrix.cpp | 99 ++++++ .../benchmark/eigen/data_generator.hpp | 16 +- .../benchmark/vc_aos/data_generator.hpp | 26 +- benchmarks/vc_aos/vc_aos_matrix.cpp | 99 ++++++ .../benchmark/vc_soa/data_generator.hpp | 31 +- benchmarks/vc_soa/vc_soa_matrix.cpp | 109 +++++++ extern/vc/CMakeLists.txt | 2 +- frontend/vc_aos/include/algebra/vc_aos.hpp | 8 +- .../algebra/math/impl/vc_aos_matrix.hpp | 53 ++-- .../algebra/math/impl/vc_aos_transform3.hpp | 30 +- .../array/include/algebra/storage/array.hpp | 3 + .../algebra/storage/array_operators.hpp | 12 +- .../common/include/algebra/storage/matrix.hpp | 293 +++++++++++++----- .../common/include/algebra/storage/vector.hpp | 155 +++++---- .../eigen/include/algebra/storage/eigen.hpp | 3 + .../vc_soa/include/algebra/storage/vc_soa.hpp | 2 +- tests/common/test_host_basics.hpp | 8 +- 25 files changed, 1108 insertions(+), 218 deletions(-) create mode 100644 benchmarks/array/array_matrix.cpp create mode 100644 benchmarks/common/include/benchmark/common/benchmark_matrix.hpp create mode 100644 benchmarks/eigen/eigen_matrix.cpp create mode 100644 benchmarks/vc_aos/vc_aos_matrix.cpp create mode 100644 benchmarks/vc_soa/vc_soa_matrix.cpp diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index ae66b7f7..6f6e24a8 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -18,10 +18,10 @@ jobs: runs-on: ubuntu-latest container: ghcr.io/acts-project/format10:v11 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Check run: .github/check_format.sh . - - uses: actions/upload-artifact@v1 + - uses: actions/upload-artifact@v4 if: failure() with: name: changed diff --git a/benchmarks/CMakeLists.txt b/benchmarks/CMakeLists.txt index f701a3ba..877caa11 100644 --- a/benchmarks/CMakeLists.txt +++ b/benchmarks/CMakeLists.txt @@ -35,6 +35,10 @@ algebra_add_benchmark( array_transform3 "array/array_transform3.cpp" LINK_LIBRARIES benchmark::benchmark algebra::bench_common algebra_bench_array algebra::array_cmath ) +algebra_add_benchmark( array_matrix + "array/array_matrix.cpp" + LINK_LIBRARIES benchmark::benchmark algebra::bench_common + algebra_bench_array algebra::array_cmath ) if( ALGEBRA_PLUGINS_INCLUDE_EIGEN ) add_library( algebra_bench_eigen INTERFACE ) @@ -54,6 +58,10 @@ if( ALGEBRA_PLUGINS_INCLUDE_EIGEN ) "eigen/eigen_transform3.cpp" LINK_LIBRARIES benchmark::benchmark algebra::bench_common algebra_bench_eigen algebra::eigen_eigen ) + algebra_add_benchmark( eigen_matrix + "eigen/eigen_matrix.cpp" + LINK_LIBRARIES benchmark::benchmark algebra::bench_common + algebra_bench_eigen algebra::eigen_eigen ) endif() if( ALGEBRA_PLUGINS_INCLUDE_VC ) @@ -75,6 +83,10 @@ if( ALGEBRA_PLUGINS_INCLUDE_VC ) "vc_aos/vc_aos_transform3.cpp" LINK_LIBRARIES benchmark::benchmark algebra::bench_common algebra_bench_vc_aos algebra::vc_aos ) + algebra_add_benchmark( vc_aos_matrix + "vc_aos/vc_aos_matrix.cpp" + LINK_LIBRARIES benchmark::benchmark algebra::bench_common + algebra_bench_vc_aos algebra::vc_aos ) if( NOT "${CMAKE_CXX_COMPILER_ID}" MATCHES "AppleClang" ) add_library( algebra_bench_vc_soa INTERFACE ) @@ -95,5 +107,9 @@ if( ALGEBRA_PLUGINS_INCLUDE_VC ) "vc_soa/vc_soa_transform3.cpp" LINK_LIBRARIES benchmark::benchmark algebra::bench_common algebra_bench_vc_soa algebra::vc_soa ) + algebra_add_benchmark( vc_soa_matrix + "vc_soa/vc_soa_matrix.cpp" + LINK_LIBRARIES benchmark::benchmark algebra::bench_common + algebra_bench_vc_soa algebra::vc_soa ) endif() endif() diff --git a/benchmarks/array/array_matrix.cpp b/benchmarks/array/array_matrix.cpp new file mode 100644 index 00000000..1654eabc --- /dev/null +++ b/benchmarks/array/array_matrix.cpp @@ -0,0 +1,99 @@ +/** Algebra plugins library, part of the ACTS project + * + * (c) 2024 CERN for the benefit of the ACTS project + * + * Mozilla Public License Version 2.0 + */ + +// Project include(s) +#include "algebra/array_cmath.hpp" +#include "benchmark/array/data_generator.hpp" +#include "benchmark/common/benchmark_matrix.hpp" +#include "benchmark/common/register_benchmark.hpp" + +// Benchmark include +#include + +using namespace algebra; + +/// Run vector benchmarks +int main(int argc, char** argv) { + + // + // Prepare benchmarks + // + algebra::benchmark_base::configuration cfg{}; + cfg.n_samples(100000); + + using mat44_add_f_t = + matrix_binaryOP_bm, bench_op::add>; + using mat44_add_d_t = + matrix_binaryOP_bm, bench_op::add>; + using mat66_add_f_t = + matrix_binaryOP_bm, bench_op::add>; + using mat66_add_d_t = + matrix_binaryOP_bm, bench_op::add>; + using mat88_add_f_t = + matrix_binaryOP_bm, bench_op::add>; + using mat88_add_d_t = + matrix_binaryOP_bm, bench_op::add>; + + using mat44_mul_f_t = + matrix_binaryOP_bm, bench_op::mul>; + using mat44_mul_d_t = + matrix_binaryOP_bm, bench_op::mul>; + using mat66_mul_f_t = + matrix_binaryOP_bm, bench_op::mul>; + using mat66_mul_d_t = + matrix_binaryOP_bm, bench_op::mul>; + using mat88_mul_f_t = + matrix_binaryOP_bm, bench_op::mul>; + using mat88_mul_d_t = + matrix_binaryOP_bm, bench_op::mul>; + + using mat44_vec_f_t = matrix_vector_bm, + array::vector_type>; + using mat44_vec_d_t = matrix_vector_bm, + array::vector_type>; + using mat66_vec_f_t = matrix_vector_bm, + array::vector_type>; + using mat66_vec_d_t = matrix_vector_bm, + array::vector_type>; + using mat88_vec_f_t = matrix_vector_bm, + array::vector_type>; + using mat88_vec_d_t = matrix_vector_bm, + array::vector_type>; + + std::cout << "-----------------------------------------------\n" + << "Algebra-Plugins 'matrix' benchmark (std::array)\n" + << "-----------------------------------------------\n\n" + << cfg; + + // + // Register all benchmarks + // + algebra::register_benchmark(cfg, "_4x4_add_single"); + algebra::register_benchmark(cfg, "_4x4_add_double"); + algebra::register_benchmark(cfg, "_6x6_add_single"); + algebra::register_benchmark(cfg, "_6x6_add_double"); + algebra::register_benchmark(cfg, "_8x8_add_single"); + algebra::register_benchmark(cfg, "_8x8_add_double"); + + algebra::register_benchmark(cfg, "_4x4_mul_single"); + algebra::register_benchmark(cfg, "_4x4_mul_double"); + algebra::register_benchmark(cfg, "_6x6_mul_single"); + algebra::register_benchmark(cfg, "_6x6_mul_double"); + algebra::register_benchmark(cfg, "_8x8_mul_single"); + algebra::register_benchmark(cfg, "_8x8_mul_double"); + + algebra::register_benchmark(cfg, "_4x4_vec_single"); + algebra::register_benchmark(cfg, "_4x4_vec_double"); + algebra::register_benchmark(cfg, "_6x6_vec_single"); + algebra::register_benchmark(cfg, "_6x6_vec_double"); + algebra::register_benchmark(cfg, "_8x8_vec_single"); + algebra::register_benchmark(cfg, "_8x8_vec_double"); + + ::benchmark::Initialize(&argc, argv); + ::benchmark::RunSpecifiedBenchmarks(); + ::benchmark::Shutdown(); +} diff --git a/benchmarks/array/include/benchmark/array/data_generator.hpp b/benchmarks/array/include/benchmark/array/data_generator.hpp index e30fc080..cf244088 100644 --- a/benchmarks/array/include/benchmark/array/data_generator.hpp +++ b/benchmarks/array/include/benchmark/array/data_generator.hpp @@ -29,10 +29,10 @@ inline void fill_random_vec(std::vector &collection) { auto rand_obj = [&]() { return vector_t{dist(mt), dist(mt), dist(mt)}; }; collection.resize(collection.capacity()); - std::generate(collection.begin(), collection.end(), rand_obj); + std::ranges::generate(collection, rand_obj); } -/// Fill a @c Vc::Vector based transform3 with random values +/// Fill a @c std::array based transform3 with random values template inline void fill_random_trf(std::vector &collection) { @@ -60,7 +60,33 @@ inline void fill_random_trf(std::vector &collection) { }; collection.resize(collection.capacity()); - std::generate(collection.begin(), collection.end(), rand_obj); + std::ranges::generate(collection, rand_obj); } -} // namespace algebra \ No newline at end of file +/// Fill a @c std::array based matrix with random values +template +inline void fill_random_matrix(std::vector &collection) { + + using scalar_t = typename matrix_t::value_type::value_type; + + // Generate a random, but valid affine transformation + std::random_device rd; + std::mt19937 mt(rd()); + std::uniform_real_distribution dist(0.f, 1.f); + auto rand_obj = [&]() { + matrix_t m; + + for (std::size_t j = 0u; j < m.size(); ++j) { + for (std::size_t i = 0u; i < m[0].size(); ++i) { + m[j][i] = dist(mt); + } + } + + return m; + }; + + collection.resize(collection.capacity()); + std::ranges::generate(collection, rand_obj); +} + +} // namespace algebra diff --git a/benchmarks/common/include/benchmark/common/benchmark_base.hpp b/benchmarks/common/include/benchmark/common/benchmark_base.hpp index 10f38dc2..c0bd8371 100644 --- a/benchmarks/common/include/benchmark/common/benchmark_base.hpp +++ b/benchmarks/common/include/benchmark/common/benchmark_base.hpp @@ -62,7 +62,7 @@ struct benchmark_base { benchmark_base() = default; /// Construct from an externally provided configuration @param cfg - benchmark_base(configuration cfg) : m_cfg{cfg} {} + explicit benchmark_base(configuration cfg) : m_cfg{cfg} {} /// @returns the benchmark configuration configuration& config() { return m_cfg; } diff --git a/benchmarks/common/include/benchmark/common/benchmark_matrix.hpp b/benchmarks/common/include/benchmark/common/benchmark_matrix.hpp new file mode 100644 index 00000000..7a03102d --- /dev/null +++ b/benchmarks/common/include/benchmark/common/benchmark_matrix.hpp @@ -0,0 +1,190 @@ +/** Algebra plugins library, part of the ACTS project + * + * (c) 2024 CERN for the benefit of the ACTS project + * + * Mozilla Public License Version 2.0 + */ + +#pragma once + +// Project include(s) +#include "benchmark_base.hpp" + +// System include(s) +#include +#include +#include +#include +#include + +namespace algebra { + +template +void fill_random_matrix(std::vector&); + +template +void fill_random_vec(std::vector&); + +/// Benchmark for vector operations +template +struct matrix_bm : public benchmark_base { + + /// Prefix for the benchmark name + inline static const std::string name{"matrix"}; + + std::vector a; + std::vector b; + + /// No default construction: Cannot prepare data + matrix_bm() = delete; + + /// Construct from an externally provided configuration @param cfg + explicit matrix_bm(benchmark_base::configuration cfg) : benchmark_base{cfg} { + + const std::size_t n_data{this->m_cfg.n_samples()}; + + a.reserve(n_data); + b.reserve(n_data); + + fill_random_matrix(a); + fill_random_matrix(b); + } + + matrix_bm(const matrix_bm& bm) = default; + matrix_bm& operator=(matrix_bm& other) = default; + + /// Clear state + ~matrix_bm() override { + a.clear(); + b.clear(); + } +}; + +/// Benchmark elementwise addition of vectors + +template +struct matrix_unaryOP_bm : public matrix_bm { + using base_type = matrix_bm; + + matrix_unaryOP_bm() = delete; + explicit matrix_unaryOP_bm(benchmark_base::configuration cfg) + : base_type{cfg} {} + matrix_unaryOP_bm(const matrix_unaryOP_bm& bm) = default; + matrix_unaryOP_bm& operator=(matrix_unaryOP_bm& other) = default; + + std::string name() const override { + return base_type::name + "_" + unaryOP::name; + } + + void operator()(::benchmark::State& state) override { + + using result_t = std::invoke_result_t; + + const std::size_t n_samples{this->m_cfg.n_samples()}; + + // Run the benchmark + for (auto _ : state) { + for (std::size_t i{0}; i < n_samples; ++i) { + result_t result = unaryOP{}(this->a[i]); + ::benchmark::DoNotOptimize(result); + } + } + } +}; + +/// Benchmark elementwise addition of vectors +template +struct matrix_binaryOP_bm : public matrix_bm { + using base_type = matrix_bm; + + matrix_binaryOP_bm() = delete; + explicit matrix_binaryOP_bm(benchmark_base::configuration cfg) + : base_type{cfg} {} + matrix_binaryOP_bm(const matrix_binaryOP_bm& bm) = default; + matrix_binaryOP_bm& operator=(matrix_binaryOP_bm& other) = default; + + std::string name() const override { + return base_type::name + "_" + binaryOP::name; + } + + void operator()(::benchmark::State& state) override { + + using result_t = std::invoke_result_t; + + const std::size_t n_samples{this->m_cfg.n_samples()}; + + // Run the benchmark + for (auto _ : state) { + for (std::size_t i{0}; i < n_samples; ++i) { + result_t result = binaryOP{}(this->a[i], this->b[i]); + ::benchmark::DoNotOptimize(result); + } + } + } +}; + +/// Benchmark matrix vector multiplication +template +struct matrix_vector_bm : public matrix_bm { + using base_type = matrix_bm; + + std::vector v; + + matrix_vector_bm() = delete; + explicit matrix_vector_bm(benchmark_base::configuration cfg) + : base_type{cfg} { + + v.reserve(this->m_cfg.n_samples()); + + fill_random_vec(v); + } + matrix_vector_bm(const matrix_vector_bm& bm) = default; + matrix_vector_bm& operator=(matrix_vector_bm& other) = default; + + /// Clear state + ~matrix_vector_bm() override { v.clear(); } + + std::string name() const override { return base_type::name + "_vector"; } + + void operator()(::benchmark::State& state) override { + + const std::size_t n_samples{this->m_cfg.n_samples()}; + + // Run the benchmark + for (auto _ : state) { + for (std::size_t i{0}; i < n_samples; ++i) { + vector_t result = this->a[i] * this->v[i]; + ::benchmark::DoNotOptimize(result); + } + } + } +}; + +// Functions to be benchmarked +namespace bench_op { + +struct add { + inline static const std::string name{"add"}; + template + matrix_t operator()(const matrix_t& a, const matrix_t& b) const { + return a + b; + } +}; +struct sub { + inline static const std::string name{"sub"}; + template + matrix_t operator()(const matrix_t& a, const matrix_t& b) const { + return a - b; + } +}; +struct mul { + inline static const std::string name{"mul"}; + template + matrix_t operator()(const matrix_t& a, const matrix_t& b) const { + return a * b; + } +}; + +} // namespace bench_op + +} // namespace algebra diff --git a/benchmarks/common/include/benchmark/common/benchmark_transform3.hpp b/benchmarks/common/include/benchmark/common/benchmark_transform3.hpp index e5d092e9..1c0e84d3 100644 --- a/benchmarks/common/include/benchmark/common/benchmark_transform3.hpp +++ b/benchmarks/common/include/benchmark/common/benchmark_transform3.hpp @@ -20,7 +20,7 @@ namespace algebra { template -void fill_random_trf(std::vector &); +void fill_random_trf(std::vector&); /// Benchmark for vector operations template @@ -36,21 +36,23 @@ struct transform3_bm : public vector_bm { /// No default construction: Cannot prepare data transform3_bm() = delete; - std::string name() const override { return base_type::name + "_" + bm_name; } - /// Construct from an externally provided configuration @param cfg - transform3_bm(benchmark_base::configuration cfg) : base_type{cfg} { + explicit transform3_bm(benchmark_base::configuration cfg) : base_type{cfg} { trfs.reserve(this->m_cfg.n_samples()); fill_random_trf(trfs); } + transform3_bm(const transform3_bm& bm) = default; + transform3_bm& operator=(transform3_bm& other) = default; /// Clear state - virtual ~transform3_bm() { trfs.clear(); } + ~transform3_bm() override { trfs.clear(); } + + std::string name() const override { return base_type::name + "_" + bm_name; } /// Benchmark case - void operator()(::benchmark::State &state) override { + void operator()(::benchmark::State& state) override { using vector_t = typename transform3_t::vector3; using point_t = typename transform3_t::point3; diff --git a/benchmarks/common/include/benchmark/common/benchmark_vector.hpp b/benchmarks/common/include/benchmark/common/benchmark_vector.hpp index 7a5b52c1..cb128012 100644 --- a/benchmarks/common/include/benchmark/common/benchmark_vector.hpp +++ b/benchmarks/common/include/benchmark/common/benchmark_vector.hpp @@ -35,7 +35,7 @@ struct vector_bm : public benchmark_base { vector_bm() = delete; /// Construct from an externally provided configuration @param cfg - vector_bm(benchmark_base::configuration cfg) : benchmark_base{cfg} { + explicit vector_bm(benchmark_base::configuration cfg) : benchmark_base{cfg} { const std::size_t n_data{this->m_cfg.n_samples()}; @@ -45,9 +45,11 @@ struct vector_bm : public benchmark_base { fill_random_vec(a); fill_random_vec(b); } + vector_bm(const vector_bm &bm) = default; + vector_bm &operator=(vector_bm &other) = default; /// Clear state - virtual ~vector_bm() { + ~vector_bm() override { a.clear(); b.clear(); } @@ -60,7 +62,11 @@ struct vector_unaryOP_bm : public vector_bm> { using base_type = vector_bm>; vector_unaryOP_bm() = delete; - vector_unaryOP_bm(benchmark_base::configuration cfg) : base_type{cfg} {} + explicit vector_unaryOP_bm(benchmark_base::configuration cfg) + : base_type{cfg} {} + vector_unaryOP_bm(const vector_unaryOP_bm &bm) = default; + vector_unaryOP_bm &operator=(vector_unaryOP_bm &other) = default; + std::string name() const override { return base_type::name + "_" + unaryOP::name; } @@ -88,7 +94,11 @@ struct vector_binaryOP_bm : public vector_bm> { using base_type = vector_bm>; vector_binaryOP_bm() = delete; - vector_binaryOP_bm(benchmark_base::configuration cfg) : base_type{cfg} {} + explicit vector_binaryOP_bm(benchmark_base::configuration cfg) + : base_type{cfg} {} + vector_binaryOP_bm(const vector_binaryOP_bm &bm) = default; + vector_binaryOP_bm &operator=(vector_binaryOP_bm &other) = default; + std::string name() const override { return base_type::name + "_" + binaryOP::name; } diff --git a/benchmarks/eigen/eigen_matrix.cpp b/benchmarks/eigen/eigen_matrix.cpp new file mode 100644 index 00000000..f0d41b11 --- /dev/null +++ b/benchmarks/eigen/eigen_matrix.cpp @@ -0,0 +1,99 @@ +/** Algebra plugins library, part of the ACTS project + * + * (c) 2024 CERN for the benefit of the ACTS project + * + * Mozilla Public License Version 2.0 + */ + +// Project include(s) +#include "algebra/eigen_eigen.hpp" +#include "benchmark/common/benchmark_matrix.hpp" +#include "benchmark/common/register_benchmark.hpp" +#include "benchmark/eigen/data_generator.hpp" + +// Benchmark include +#include + +using namespace algebra; + +/// Run vector benchmarks +int main(int argc, char** argv) { + + // + // Prepare benchmarks + // + algebra::benchmark_base::configuration cfg{}; + cfg.n_samples(100000); + + using mat44_add_f_t = + matrix_binaryOP_bm, bench_op::add>; + using mat44_add_d_t = + matrix_binaryOP_bm, bench_op::add>; + using mat66_add_f_t = + matrix_binaryOP_bm, bench_op::add>; + using mat66_add_d_t = + matrix_binaryOP_bm, bench_op::add>; + using mat88_add_f_t = + matrix_binaryOP_bm, bench_op::add>; + using mat88_add_d_t = + matrix_binaryOP_bm, bench_op::add>; + + using mat44_mul_f_t = + matrix_binaryOP_bm, bench_op::mul>; + using mat44_mul_d_t = + matrix_binaryOP_bm, bench_op::mul>; + using mat66_mul_f_t = + matrix_binaryOP_bm, bench_op::mul>; + using mat66_mul_d_t = + matrix_binaryOP_bm, bench_op::mul>; + using mat88_mul_f_t = + matrix_binaryOP_bm, bench_op::mul>; + using mat88_mul_d_t = + matrix_binaryOP_bm, bench_op::mul>; + + using mat44_vec_f_t = matrix_vector_bm, + eigen::vector_type>; + using mat44_vec_d_t = matrix_vector_bm, + eigen::vector_type>; + using mat66_vec_f_t = matrix_vector_bm, + eigen::vector_type>; + using mat66_vec_d_t = matrix_vector_bm, + eigen::vector_type>; + using mat88_vec_f_t = matrix_vector_bm, + eigen::vector_type>; + using mat88_vec_d_t = matrix_vector_bm, + eigen::vector_type>; + + std::cout << "------------------------------------------\n" + << "Algebra-Plugins 'matrix' benchmark (Eigen3)\n" + << "-------------------------------------------\n\n" + << cfg; + + // + // Register all benchmarks + // + algebra::register_benchmark(cfg, "_4x4_add_single"); + algebra::register_benchmark(cfg, "_4x4_add_double"); + algebra::register_benchmark(cfg, "_6x6_add_single"); + algebra::register_benchmark(cfg, "_6x6_add_double"); + algebra::register_benchmark(cfg, "_8x8_add_single"); + algebra::register_benchmark(cfg, "_8x8_add_double"); + + algebra::register_benchmark(cfg, "_4x4_mul_single"); + algebra::register_benchmark(cfg, "_4x4_mul_double"); + algebra::register_benchmark(cfg, "_6x6_mul_single"); + algebra::register_benchmark(cfg, "_6x6_mul_double"); + algebra::register_benchmark(cfg, "_8x8_mul_single"); + algebra::register_benchmark(cfg, "_8x8_mul_double"); + + algebra::register_benchmark(cfg, "_4x4_vec_single"); + algebra::register_benchmark(cfg, "_4x4_vec_double"); + algebra::register_benchmark(cfg, "_6x6_vec_single"); + algebra::register_benchmark(cfg, "_6x6_vec_double"); + algebra::register_benchmark(cfg, "_8x8_vec_single"); + algebra::register_benchmark(cfg, "_8x8_vec_double"); + + ::benchmark::Initialize(&argc, argv); + ::benchmark::RunSpecifiedBenchmarks(); + ::benchmark::Shutdown(); +} diff --git a/benchmarks/eigen/include/benchmark/eigen/data_generator.hpp b/benchmarks/eigen/include/benchmark/eigen/data_generator.hpp index 5b1b3a37..21560406 100644 --- a/benchmarks/eigen/include/benchmark/eigen/data_generator.hpp +++ b/benchmarks/eigen/include/benchmark/eigen/data_generator.hpp @@ -23,7 +23,7 @@ inline void fill_random_vec(std::vector &collection) { auto rand_obj = []() { return vector_t::Random(); }; collection.resize(collection.capacity()); - std::generate(collection.begin(), collection.end(), rand_obj); + std::ranges::generate(collection, rand_obj); } /// Fill a @c Eigen3 based transform3 with random values @@ -48,7 +48,17 @@ inline void fill_random_trf(std::vector &collection) { }; collection.resize(collection.capacity()); - std::generate(collection.begin(), collection.end(), rand_obj); + std::ranges::generate(collection, rand_obj); } -} // namespace algebra \ No newline at end of file +/// Fill a @c Eigen3 based matrix with random values +template +inline void fill_random_matrix(std::vector &collection) { + + auto rand_obj = []() { return matrix_t::Random(); }; + + collection.resize(collection.capacity()); + std::ranges::generate(collection, rand_obj); +} + +} // namespace algebra diff --git a/benchmarks/vc_aos/include/benchmark/vc_aos/data_generator.hpp b/benchmarks/vc_aos/include/benchmark/vc_aos/data_generator.hpp index 21874cff..2d28a50c 100644 --- a/benchmarks/vc_aos/include/benchmark/vc_aos/data_generator.hpp +++ b/benchmarks/vc_aos/include/benchmark/vc_aos/data_generator.hpp @@ -26,7 +26,7 @@ inline void fill_random_vec(std::vector &collection) { }; collection.resize(collection.capacity()); - std::generate(collection.begin(), collection.end(), rand_obj); + std::ranges::generate(collection, rand_obj); } /// Fill a @c Vc::SimdArray based transform3 with random values @@ -55,7 +55,29 @@ inline void fill_random_trf(std::vector &collection) { }; collection.resize(collection.capacity()); - std::generate(collection.begin(), collection.end(), rand_obj); + std::ranges::generate(collection, rand_obj); +} + +/// Fill a @c Vc::SimdArray based matrix with random values +template +inline void fill_random_matrix(std::vector &collection) { + // Generate a random, but valid affine transformation + auto rand_obj = []() { + using vector_t = typename matrix_t::vector_type; + vector_t x_axis; + vector_t z_axis; + vector_t t; + + matrix_t m; + for (std::size_t j = 0u; j < matrix_t::columns(); ++j) { + m[j] = vector_t::array_type::Random(); + } + + return m; + }; + + collection.resize(collection.capacity()); + std::ranges::generate(collection, rand_obj); } } // namespace algebra diff --git a/benchmarks/vc_aos/vc_aos_matrix.cpp b/benchmarks/vc_aos/vc_aos_matrix.cpp new file mode 100644 index 00000000..6c63abbc --- /dev/null +++ b/benchmarks/vc_aos/vc_aos_matrix.cpp @@ -0,0 +1,99 @@ +/** Algebra plugins library, part of the ACTS project + * + * (c) 2024 CERN for the benefit of the ACTS project + * + * Mozilla Public License Version 2.0 + */ + +// Project include(s) +#include "algebra/vc_aos.hpp" +#include "benchmark/common/benchmark_matrix.hpp" +#include "benchmark/common/register_benchmark.hpp" +#include "benchmark/vc_aos/data_generator.hpp" + +// Benchmark include +#include + +using namespace algebra; + +/// Run vector benchmarks +int main(int argc, char** argv) { + + // + // Prepare benchmarks + // + algebra::benchmark_base::configuration cfg{}; + cfg.n_samples(100000); + + using mat44_add_f_t = + matrix_binaryOP_bm, bench_op::add>; + using mat44_add_d_t = + matrix_binaryOP_bm, bench_op::add>; + using mat66_add_f_t = + matrix_binaryOP_bm, bench_op::add>; + using mat66_add_d_t = + matrix_binaryOP_bm, bench_op::add>; + using mat88_add_f_t = + matrix_binaryOP_bm, bench_op::add>; + using mat88_add_d_t = + matrix_binaryOP_bm, bench_op::add>; + + using mat44_mul_f_t = + matrix_binaryOP_bm, bench_op::mul>; + using mat44_mul_d_t = + matrix_binaryOP_bm, bench_op::mul>; + using mat66_mul_f_t = + matrix_binaryOP_bm, bench_op::mul>; + using mat66_mul_d_t = + matrix_binaryOP_bm, bench_op::mul>; + using mat88_mul_f_t = + matrix_binaryOP_bm, bench_op::mul>; + using mat88_mul_d_t = + matrix_binaryOP_bm, bench_op::mul>; + + using mat44_vec_f_t = matrix_vector_bm, + vc_aos::vector_type>; + using mat44_vec_d_t = matrix_vector_bm, + vc_aos::vector_type>; + using mat66_vec_f_t = matrix_vector_bm, + vc_aos::vector_type>; + using mat66_vec_d_t = matrix_vector_bm, + vc_aos::vector_type>; + using mat88_vec_f_t = matrix_vector_bm, + vc_aos::vector_type>; + using mat88_vec_d_t = matrix_vector_bm, + vc_aos::vector_type>; + + std::cout << "------------------------------------------\n" + << "Algebra-Plugins 'matrix' benchmark (Vc AoS)\n" + << "-------------------------------------------\n\n" + << cfg; + + // + // Register all benchmarks + // + algebra::register_benchmark(cfg, "_4x4_add_single"); + algebra::register_benchmark(cfg, "_4x4_add_double"); + algebra::register_benchmark(cfg, "_6x6_add_single"); + algebra::register_benchmark(cfg, "_6x6_add_double"); + algebra::register_benchmark(cfg, "_8x8_add_single"); + algebra::register_benchmark(cfg, "_8x8_add_double"); + + algebra::register_benchmark(cfg, "_4x4_mul_single"); + algebra::register_benchmark(cfg, "_4x4_mul_double"); + algebra::register_benchmark(cfg, "_6x6_mul_single"); + algebra::register_benchmark(cfg, "_6x6_mul_double"); + algebra::register_benchmark(cfg, "_8x8_mul_single"); + algebra::register_benchmark(cfg, "_8x8_mul_double"); + + algebra::register_benchmark(cfg, "_4x4_vec_single"); + algebra::register_benchmark(cfg, "_4x4_vec_double"); + algebra::register_benchmark(cfg, "_6x6_vec_single"); + algebra::register_benchmark(cfg, "_6x6_vec_double"); + algebra::register_benchmark(cfg, "_8x8_vec_single"); + algebra::register_benchmark(cfg, "_8x8_vec_double"); + + ::benchmark::Initialize(&argc, argv); + ::benchmark::RunSpecifiedBenchmarks(); + ::benchmark::Shutdown(); +} diff --git a/benchmarks/vc_soa/include/benchmark/vc_soa/data_generator.hpp b/benchmarks/vc_soa/include/benchmark/vc_soa/data_generator.hpp index b519a795..a4300af6 100644 --- a/benchmarks/vc_soa/include/benchmark/vc_soa/data_generator.hpp +++ b/benchmarks/vc_soa/include/benchmark/vc_soa/data_generator.hpp @@ -30,7 +30,7 @@ inline void fill_random_vec(std::vector &collection) { }; collection.resize(collection.capacity()); - std::generate(collection.begin(), collection.end(), rand_obj); + std::ranges::generate(collection, rand_obj); } /// Fill a @c Vc::Vector based transform3 with random values @@ -62,7 +62,34 @@ inline void fill_random_trf(std::vector &collection) { }; collection.resize(collection.capacity()); - std::generate(collection.begin(), collection.end(), rand_obj); + std::ranges::generate(collection, rand_obj); +} + +/// Fill a @c Vc::Vector based matrix with random values +template +inline void fill_random_matrix(std::vector &collection) { + // Generate a random, but valid affine transformation + auto rand_obj = []() { + using simd_vector_t = typename matrix_t::value_type; + + matrix_t m; + + for (std::size_t j = 0u; j < matrix_t::columns(); ++j) { + + typename matrix_t::vector_type v; + + for (std::size_t i = 0u; i < matrix_t::rows(); ++i) { + v[i] = simd_vector_t::Random(); + + m[j] = v; + } + } + + return m; + }; + + collection.resize(collection.capacity()); + std::ranges::generate(collection, rand_obj); } } // namespace algebra diff --git a/benchmarks/vc_soa/vc_soa_matrix.cpp b/benchmarks/vc_soa/vc_soa_matrix.cpp new file mode 100644 index 00000000..4f1956aa --- /dev/null +++ b/benchmarks/vc_soa/vc_soa_matrix.cpp @@ -0,0 +1,109 @@ +/** Algebra plugins library, part of the ACTS project + * + * (c) 2024 CERN for the benefit of the ACTS project + * + * Mozilla Public License Version 2.0 + */ + +// Project include(s) +#include "algebra/vc_soa.hpp" +#include "benchmark/common/benchmark_matrix.hpp" +#include "benchmark/common/register_benchmark.hpp" +#include "benchmark/vc_soa/data_generator.hpp" + +// Benchmark include +#include + +using namespace algebra; + +/// Run vector benchmarks +int main(int argc, char** argv) { + + constexpr std::size_t n_samples{100000}; + + // + // Prepare benchmarks + // + algebra::benchmark_base::configuration cfg_s{}; + // Reduce the number of samples, since a single SoA struct contains multiple + // vectors + cfg_s.n_samples(n_samples / Vc::float_v::Size); + + // For double precision we need more samples (less vectors per SoA) + algebra::benchmark_base::configuration cfg_d{cfg_s}; + cfg_d.n_samples(n_samples / Vc::double_v::Size); + + using mat44_add_f_t = + matrix_binaryOP_bm, bench_op::add>; + using mat44_add_d_t = + matrix_binaryOP_bm, bench_op::add>; + using mat66_add_f_t = + matrix_binaryOP_bm, bench_op::add>; + using mat66_add_d_t = + matrix_binaryOP_bm, bench_op::add>; + using mat88_add_f_t = + matrix_binaryOP_bm, bench_op::add>; + using mat88_add_d_t = + matrix_binaryOP_bm, bench_op::add>; + + using mat44_mul_f_t = + matrix_binaryOP_bm, bench_op::mul>; + using mat44_mul_d_t = + matrix_binaryOP_bm, bench_op::mul>; + using mat66_mul_f_t = + matrix_binaryOP_bm, bench_op::mul>; + using mat66_mul_d_t = + matrix_binaryOP_bm, bench_op::mul>; + using mat88_mul_f_t = + matrix_binaryOP_bm, bench_op::mul>; + using mat88_mul_d_t = + matrix_binaryOP_bm, bench_op::mul>; + + using mat44_vec_f_t = matrix_vector_bm, + vc_soa::vector_type>; + using mat44_vec_d_t = matrix_vector_bm, + vc_soa::vector_type>; + using mat66_vec_f_t = matrix_vector_bm, + vc_soa::vector_type>; + using mat66_vec_d_t = matrix_vector_bm, + vc_soa::vector_type>; + using mat88_vec_f_t = matrix_vector_bm, + vc_soa::vector_type>; + using mat88_vec_d_t = matrix_vector_bm, + vc_soa::vector_type>; + + std::cout << "-------------------------------------------\n" + << "Algebra-Plugins 'matrix' benchmark (Vc SoA)\n" + << "-------------------------------------------\n\n" + << "(single)\n" + << cfg_s << "(double)\n" + << cfg_d; + + // + // Register all benchmarks + // + algebra::register_benchmark(cfg_s, "_4x4_add_single"); + algebra::register_benchmark(cfg_d, "_4x4_add_double"); + algebra::register_benchmark(cfg_s, "_6x6_add_single"); + algebra::register_benchmark(cfg_d, "_6x6_add_double"); + algebra::register_benchmark(cfg_s, "_8x8_add_single"); + algebra::register_benchmark(cfg_d, "_8x8_add_double"); + + algebra::register_benchmark(cfg_s, "_4x4_mul_single"); + algebra::register_benchmark(cfg_d, "_4x4_mul_double"); + algebra::register_benchmark(cfg_s, "_6x6_mul_single"); + algebra::register_benchmark(cfg_d, "_6x6_mul_double"); + algebra::register_benchmark(cfg_s, "_8x8_mul_single"); + algebra::register_benchmark(cfg_d, "_8x8_mul_double"); + + algebra::register_benchmark(cfg_s, "_4x4_vec_single"); + algebra::register_benchmark(cfg_d, "_4x4_vec_double"); + algebra::register_benchmark(cfg_s, "_6x6_vec_single"); + algebra::register_benchmark(cfg_d, "_6x6_vec_double"); + algebra::register_benchmark(cfg_s, "_8x8_vec_single"); + algebra::register_benchmark(cfg_d, "_8x8_vec_double"); + + ::benchmark::Initialize(&argc, argv); + ::benchmark::RunSpecifiedBenchmarks(); + ::benchmark::Shutdown(); +} diff --git a/extern/vc/CMakeLists.txt b/extern/vc/CMakeLists.txt index abc3a1ad..adb221bb 100644 --- a/extern/vc/CMakeLists.txt +++ b/extern/vc/CMakeLists.txt @@ -52,7 +52,7 @@ target_include_directories( Vc # Disable a warning for GCC which the Vc build turns on explicitly for that # compiler, just to then go and trigger it... :-/ if( "${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU" ) - target_compile_options( Vc PRIVATE "-Wno-old-style-cast" ) + target_compile_options( Vc PRIVATE "-Wno-old-style-cast -Wdeprecated-enum-enum-conversion -Wdeprecated-declarations" ) endif() # Set up an alias for the Vc target, with the same name that it will have diff --git a/frontend/vc_aos/include/algebra/vc_aos.hpp b/frontend/vc_aos/include/algebra/vc_aos.hpp index 1c72bbdc..1660d635 100644 --- a/frontend/vc_aos/include/algebra/vc_aos.hpp +++ b/frontend/vc_aos/include/algebra/vc_aos.hpp @@ -62,7 +62,7 @@ ALGEBRA_HOST_DEVICE inline const auto& vector( assert(row == 0); assert(col < COL); - return m[COL]; + return m[col]; } /// Function extracting a slice from matrix44 - non-const @@ -81,7 +81,7 @@ ALGEBRA_HOST_DEVICE inline auto& vector( assert(row == 0); assert(col < COL); - return m[COL]; + return m[col]; } /// @} @@ -106,6 +106,10 @@ namespace matrix { template using actor = vc_aos::matrix::actor; +using storage::identity; +using storage::transpose; +using storage::zero; + } // namespace matrix } // namespace algebra diff --git a/math/vc_aos/include/algebra/math/impl/vc_aos_matrix.hpp b/math/vc_aos/include/algebra/math/impl/vc_aos_matrix.hpp index 62739211..17e617d8 100644 --- a/math/vc_aos/include/algebra/math/impl/vc_aos_matrix.hpp +++ b/math/vc_aos/include/algebra/math/impl/vc_aos_matrix.hpp @@ -11,7 +11,9 @@ #include "algebra/qualifiers.hpp" #include "algebra/storage/matrix.hpp" -namespace algebra::vc_aos::matrix { +namespace algebra::vc_aos { + +namespace matrix { /// Explicitly vectorized matrix implementation template