Skip to content

Commit

Permalink
This adds a new vector wrapper class that allows for an SoA layout, i…
Browse files Browse the repository at this point in the history
…n particular, to enable us to use the Vc::Vector type efficiently. The new storage/vector keeps an array-like data structure, that holds the vector elements (say, x, y, z). Both the array type, as well as the value type of the elements are templated (storage/vector< algebraic vector dim, aos/soa value type (scalar vs e.g SIMD vector), array-like storage for the algebraic vector elements >), so that combinations like these are possible:

    3-dim AoS std::array based vector (not necessary, since this would essentially duplicate the array plugin, while begin more complicated): storage::vector<3, scalar_t, std::array>
    3-dim AoS vertical vectorized (Not there, yet, but would re-implement the current vc_vc plugin, while making the extra vc_array4 wrapper superfluous): storage::vector<3, scalar_t, Vc::SimdArray>
    3-dim SoA of size N, std::array based: storage::vector<3, std::array<scalar_t, N>, std::array>
    3-dim vetorized SoA (in this PR): storage::vector<3, Vc::Vector<scalar_t>, std::array>

Also adds benchmarks to compare to the std::array and Eigen AoS plugins.
  • Loading branch information
niermann999 committed Mar 25, 2023
1 parent b699697 commit 4ad985f
Show file tree
Hide file tree
Showing 37 changed files with 2,051 additions and 6 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,6 @@
*.exe
*.out
*.app

# Local folders
/build
74 changes: 74 additions & 0 deletions benchmarks/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Algebra plugins library, part of the ACTS project (R&D line)
#
# (c) 2023 CERN for the benefit of the ACTS project
#
# Mozilla Public License Version 2.0

# Set the default C++ compiler flags.
include( algebra-plugins-compiler-options-cpp )

# Set up an INTERFACE library for the common header(s).
add_library( algebra_bench_common INTERFACE )
target_include_directories( algebra_bench_common INTERFACE
"${CMAKE_CURRENT_SOURCE_DIR}/common/include" )
if( "${CMAKE_CXX_COMPILER_ID}" MATCHES "MSVC" )
target_compile_definitions( algebra_bench_common INTERFACE
-D_USE_MATH_DEFINES )
endif()
add_library( algebra::bench_common ALIAS algebra_bench_common )

# Set up all of the (available) "host" benchmarks.
add_library( algebra_bench_array INTERFACE )
target_include_directories( algebra_bench_array INTERFACE
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/array/include>" )
target_link_libraries(algebra_bench_array INTERFACE algebra::array_cmath
algebra::common_storage)
add_library( algebra::bench_array ALIAS algebra_bench_array )

algebra_add_benchmark( array_getter
"array/array_getter.cpp"
LINK_LIBRARIES benchmark::benchmark algebra::bench_common
algebra::bench_array algebra::array_cmath )
algebra_add_benchmark( array_vector
"array/array_vector.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 )
target_include_directories( algebra_bench_eigen INTERFACE
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/eigen/include>" )
target_link_libraries(algebra_bench_eigen INTERFACE algebra::eigen_eigen
algebra::common_storage)
add_library( algebra::bench_eigen ALIAS algebra_bench_eigen )

algebra_add_benchmark( eigen_getter
"eigen/eigen_getter.cpp"
LINK_LIBRARIES benchmark::benchmark algebra::bench_common
algebra::bench_eigen algebra::eigen_eigen )
algebra_add_benchmark( eigen_vector
"eigen/eigen_vector.cpp"
LINK_LIBRARIES benchmark::benchmark algebra::bench_common
algebra::bench_eigen algebra::eigen_eigen )
endif()

if( ALGEBRA_PLUGINS_INCLUDE_VC )
if( NOT "${CMAKE_CXX_COMPILER_ID}" MATCHES "AppleClang" )
add_library( algebra_bench_vc_soa INTERFACE )
target_include_directories( algebra_bench_vc_soa INTERFACE
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/vc_soa/include>" )
target_link_libraries(algebra_bench_vc_soa INTERFACE
algebra::vc_soa
algebra::common_storage)
add_library( algebra::bench_vc_soa ALIAS algebra_bench_vc_soa )

algebra_add_benchmark( vc_soa_getter
"vc_soa/vc_soa_getter.cpp"
LINK_LIBRARIES benchmark::benchmark algebra::bench_common
algebra::bench_vc_soa algebra::vc_soa )
algebra_add_benchmark( vc_soa_vector
"vc_soa/vc_soa_vector.cpp"
LINK_LIBRARIES benchmark::benchmark algebra::bench_common
algebra::bench_vc_soa algebra::vc_soa )
endif()
endif()
93 changes: 93 additions & 0 deletions benchmarks/array/array_getter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/** Algebra plugins library, part of the ACTS project
*
* (c) 2023 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_getter.hpp"

// Benchmark include
#include <benchmark/benchmark.h>

// System include(s)
#include <string>

using namespace algebra;

/// Run vector benchmarks
int main(int argc, char** argv) {

constexpr std::size_t n_samples{160000};
constexpr std::size_t n_warmup{static_cast<std::size_t>(0.1 * n_samples)};

//
// Prepare benchmarks
//
algebra::benchmark_base::configuration cfg{};
cfg.n_samples(n_samples).n_warmup(n_warmup);
cfg.do_sleep(false);

vector_unaryOP_bm<array::vector3, float, bench_op::phi> v_phi_s{cfg};
vector_unaryOP_bm<array::vector3, float, bench_op::theta> v_theta_s{cfg};
vector_unaryOP_bm<array::vector3, float, bench_op::perp> v_perp_s{cfg};
vector_unaryOP_bm<array::vector3, float, bench_op::norm> v_norm_s{cfg};
vector_unaryOP_bm<array::vector3, float, bench_op::eta> v_eta_s{cfg};

vector_unaryOP_bm<array::vector3, double, bench_op::phi> v_phi_d{cfg};
vector_unaryOP_bm<array::vector3, double, bench_op::theta> v_theta_d{cfg};
vector_unaryOP_bm<array::vector3, double, bench_op::perp> v_perp_d{cfg};
vector_unaryOP_bm<array::vector3, double, bench_op::norm> v_norm_d{cfg};
vector_unaryOP_bm<array::vector3, double, bench_op::eta> v_eta_d{cfg};

std::cout << "Algebra-Plugins 'getter' benchmark (std::array)\n"
<< "-----------------------------------------------\n\n"
<< cfg;

//
// Register all benchmarks
//
::benchmark::RegisterBenchmark((v_phi_s.name() + "_single").c_str(), v_phi_s)
->MeasureProcessCPUTime()
->ThreadPerCpu();
::benchmark::RegisterBenchmark((v_phi_d.name() + "_double").c_str(), v_phi_d)
->MeasureProcessCPUTime()
->ThreadPerCpu();
::benchmark::RegisterBenchmark((v_theta_s.name() + "_single").c_str(),
v_theta_s)
->MeasureProcessCPUTime()
->ThreadPerCpu();
::benchmark::RegisterBenchmark((v_theta_d.name() + "_double").c_str(),
v_theta_d)
->MeasureProcessCPUTime()
->ThreadPerCpu();
::benchmark::RegisterBenchmark((v_perp_s.name() + "_single").c_str(),
v_perp_s)
->MeasureProcessCPUTime()
->ThreadPerCpu();
::benchmark::RegisterBenchmark((v_perp_d.name() + "_double").c_str(),
v_perp_d)
->MeasureProcessCPUTime()
->ThreadPerCpu();
::benchmark::RegisterBenchmark((v_norm_s.name() + "_single").c_str(),
v_norm_s)
->MeasureProcessCPUTime()
->ThreadPerCpu();
::benchmark::RegisterBenchmark((v_norm_d.name() + "_double").c_str(),
v_norm_d)
->MeasureProcessCPUTime()
->ThreadPerCpu();
::benchmark::RegisterBenchmark((v_eta_s.name() + "_single").c_str(), v_eta_s)
->MeasureProcessCPUTime()
->ThreadPerCpu();
::benchmark::RegisterBenchmark((v_eta_d.name() + "_double").c_str(), v_eta_d)
->MeasureProcessCPUTime()
->ThreadPerCpu();

::benchmark::Initialize(&argc, argv);
::benchmark::RunSpecifiedBenchmarks();
::benchmark::Shutdown();
}
93 changes: 93 additions & 0 deletions benchmarks/array/array_vector.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/** Algebra plugins library, part of the ACTS project
*
* (c) 2023 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_vector.hpp"

// Benchmark include
#include <benchmark/benchmark.h>

// System include(s)
#include <string>

using namespace algebra;

/// Run vector benchmarks
int main(int argc, char** argv) {

constexpr std::size_t n_samples{160000};
constexpr std::size_t n_warmup{static_cast<std::size_t>(0.1 * n_samples)};

//
// Prepare benchmarks
//
algebra::benchmark_base::configuration cfg{};
cfg.n_samples(n_samples).n_warmup(n_warmup);
cfg.do_sleep(false);

vector_binaryOP_bm<array::vector3, float, bench_op::add> v_add_s{cfg};
vector_binaryOP_bm<array::vector3, float, bench_op::sub> v_sub_s{cfg};
vector_binaryOP_bm<array::vector3, float, bench_op::dot> v_dot_s{cfg};
vector_binaryOP_bm<array::vector3, float, bench_op::cross> v_cross_s{cfg};
vector_unaryOP_bm<array::vector3, float, bench_op::normalize> v_normalize_s{
cfg};

vector_binaryOP_bm<array::vector3, double, bench_op::add> v_add_d{cfg};
vector_binaryOP_bm<array::vector3, double, bench_op::sub> v_sub_d{cfg};
vector_binaryOP_bm<array::vector3, double, bench_op::dot> v_dot_d{cfg};
vector_binaryOP_bm<array::vector3, double, bench_op::cross> v_cross_d{cfg};
vector_unaryOP_bm<array::vector3, double, bench_op::normalize> v_normalize_d{
cfg};

std::cout << "Algebra-Plugins 'vector' benchmark (std::array)\n"
<< "-----------------------------------------------\n\n"
<< cfg;

//
// Register all benchmarks
//
::benchmark::RegisterBenchmark((v_add_s.name() + "_single").c_str(), v_add_s)
->MeasureProcessCPUTime()
->ThreadPerCpu();
::benchmark::RegisterBenchmark((v_add_d.name() + "_double").c_str(), v_add_d)
->MeasureProcessCPUTime()
->ThreadPerCpu();
::benchmark::RegisterBenchmark((v_sub_s.name() + "_single").c_str(), v_sub_s)
->MeasureProcessCPUTime()
->ThreadPerCpu();
::benchmark::RegisterBenchmark((v_sub_d.name() + "_double").c_str(), v_sub_d)
->MeasureProcessCPUTime()
->ThreadPerCpu();
::benchmark::RegisterBenchmark((v_dot_s.name() + "_single").c_str(), v_dot_s)
->MeasureProcessCPUTime()
->ThreadPerCpu();
::benchmark::RegisterBenchmark((v_dot_d.name() + "_double").c_str(), v_dot_d)
->MeasureProcessCPUTime()
->ThreadPerCpu();
::benchmark::RegisterBenchmark((v_cross_s.name() + "_single").c_str(),
v_cross_s)
->MeasureProcessCPUTime()
->ThreadPerCpu();
::benchmark::RegisterBenchmark((v_cross_d.name() + "_double").c_str(),
v_cross_d)
->MeasureProcessCPUTime()
->ThreadPerCpu();
::benchmark::RegisterBenchmark((v_normalize_s.name() + "_single").c_str(),
v_normalize_s)
->MeasureProcessCPUTime()
->ThreadPerCpu();
::benchmark::RegisterBenchmark((v_normalize_d.name() + "_double").c_str(),
v_normalize_d)
->MeasureProcessCPUTime()
->ThreadPerCpu();

::benchmark::Initialize(&argc, argv);
::benchmark::RunSpecifiedBenchmarks();
::benchmark::Shutdown();
}
32 changes: 32 additions & 0 deletions benchmarks/array/include/benchmark/array/data_generator.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/** Algebra plugins library, part of the ACTS project
*
* (c) 2023 CERN for the benefit of the ACTS project
*
* Mozilla Public License Version 2.0
*/

#pragma once

// System include(s)
#include <algorithm>
#include <random>
#include <vector>

namespace algebra {

/// Fill an @c std::array based vector with random values
template <typename vector_t>
inline void fill_random(std::vector<vector_t> &collection) {

// Generate a vector of the right type with random values
std::random_device rd;
std::mt19937 mt(rd());
std::uniform_real_distribution<typename vector_t::value_type> dist(0.f, 1.f);

auto rand_obj = [&]() { return vector_t{dist(mt), dist(mt), dist(mt)}; };

collection.resize(collection.capacity());
std::generate(collection.begin(), collection.end(), rand_obj);
}

} // namespace algebra
Loading

0 comments on commit 4ad985f

Please sign in to comment.