diff --git a/benchmarks/common/python/plot_benchmarks.py b/benchmarks/common/python/plot_benchmarks.py new file mode 100644 index 00000000..05de102e --- /dev/null +++ b/benchmarks/common/python/plot_benchmarks.py @@ -0,0 +1,167 @@ +# Algebra plugins library, part of the ACTS project +# +# (c) 2024 CERN for the benefit of the ACTS project +# +# Mozilla Public License Version 2.0 + +# python includes +import argparse +import logging +import json +import pandas as pd +import os +import sys +from datetime import datetime +import pathlib + +""" Parse commandline arguments """ +def parse_arguments(): +#----------------------------------------------------------------arg parsing + + parser = argparse.ArgumentParser(description = "Compare benchmarks") + parser.add_argument("--debug", "-d", + help=("Enables debug output"), + action="store_true") + parser.add_argument("--logfile", + help=("Write log in file"), + default = "", type=str) + parser.add_argument("--input", "-i", nargs='+', + help=("Input material scan data file."), + default = "", type=str) + parser.add_argument("--outdir", "-o", + help=("Output directory for plots."), + default = "./material_plots/", type=str) + parser.add_argument("--output_format", "-of", + help=("Format of the plot files (svg|png|pdf)."), + default = "png", type=str) + + args = parser.parse_args() + +#---------------------------------------------------------------------config + + # Check output path + if not os.path.isdir(args.outdir): + os.mkdir(args.outdir, 0o755) + outdir = args.outdir + + # Check input data files + if len(args.input) == 0: + logging.error(f"Please specify an input data file!") + sys.exit(1) + + for input_file in args.input: + if not os.path.isfile(input_file): + logging.error(f"Data file does not exist! ({input_file})") + sys.exit(1) + + if not args.output_format in ["svg", "png", "pdf"]: + logging.error(f"Unknown output file format: {args.output_format}") + sys.exit(1) + + # Set log level + logLevel = logging.INFO + if args.debug: + logLevel = logging.DEBUG + + # Check logfile path + if args.logfile != "": + logDirName = os.path.dirname(args.logfile) + + if logDirName != "" and not os.path.isdir(logDirName): + os.mkdir(logDirName, 0o755) + + if not os.path.isfile(args.logfile): + with open(args.logfile, 'x'): pass + + # Write log in logfile + logging.basicConfig(filename=args.logfile, + format=("%(levelname)s (%(module)s):" + " %(message)s"), level=logLevel) + else: + # Write log to terminal + logging.basicConfig(format=("%(levelname)s (%(module)s):" + " %(message)s"), level=logLevel) + + logging.info("\n--------------------------------------------------------\n" + "Plotting benchmarks - "+\ + str(datetime.now().strftime("%d/%m/%Y %H:%M"))+\ + "\n->files: " + str(len(args.input)) +\ + "\n--------------------------------------------------------\n") + + return args + +#----------------------------------------------------------------prepare data + +"""Read benchmark data into pandas frame""" +def read_data(args): + + benchmarks = {} + for input_file in args.input: + with open(input_file, 'r') as file: + extension = pathlib.Path(input_file).suffix + name = input_file.removesuffix(extension) + try: + json_data = json.load(file) + benchmarks[name] = pd.DataFrame(json_data["benchmarks"]) + except ValueError: + logging.error('Could not parse the benchmark data') + exit(1) + + benchmarks[name]['label'] = benchmarks[name]['name'].apply(lambda x: x.split("/")[0].split("_")[1:]) + + return benchmarks + + +"""Display the benchmark data""" +def plot_benchmarks(data, args): + x = np.arange(len(data[0] / 3)) # Always three entries per benchmark case + width = 0.15 # the width of the bars + + # Reorganize into benchmark families + families = {} + for plugin in data: + for index, row in df.sort_values(by=['family_index']).iterrows(): + print(row['familiy_index']) + + + bars_eigen = ax.bar(x - 1.5*width, eigen, width, label='eigen', yerr=eigen_err) + bars_AoS = ax.bar(x - 0.5*width, AoS, width, label='AoS', yerr=AoS_err) + bars_hybrid = ax.bar(x + 0.5*width, hybrid, width, label='hybrid', yerr=hybrid_err) + bars_horiz = ax.bar(x + 1.5*width, horiz, width, label='horiz', yerr=horiz_err) + + + fig, ax = plt.subplots() + + # Add some text for labels, title and custom x-axis tick labels, etc. + ax.set_ylabel('speedup') + ax.set_title('speed up relative to Eigen sse(double) - preliminary') + ax.set_xticks(x) + ax.set_xticklabels(labels) + ax.legend() + + autolabel(bars_eigen, ax) + autolabel(bars_AoS, ax) + autolabel(bars_hybrid, ax) + autolabel(bars_horiz, ax) + + fig.tight_layout() + + plot_file_name = "./aggregate_plots/speedup_comparision.png" + fig.savefig(plot_file_name, dpi=100) + fig.clf() + plt.close(fig) + + +def main(): + args = parse_arguments() + data = read_data(args) + plot_benchmarks(data, args) + + print(data['vc_aos_vector_bench']) + +#------------------------------------------------------------------------------- + +if __name__ == "__main__": + main() + +#------------------------------------------------------------------------------- diff --git a/frontend/vc_aos/include/algebra/vc_aos.hpp b/frontend/vc_aos/include/algebra/vc_aos.hpp index 4245f9d1..a32c3926 100644 --- a/frontend/vc_aos/include/algebra/vc_aos.hpp +++ b/frontend/vc_aos/include/algebra/vc_aos.hpp @@ -23,7 +23,7 @@ namespace vc_aos { /// @{ template -using transform3 = math::transform3, point2>; +using transform3 = math::transform3; /// @} @@ -42,11 +42,17 @@ using vc_aos::math::theta; /// @} -/// Function extracting a slice from the matrix used by -/// @c algebra::vc_aos::transform3 -template = true> -ALGEBRA_HOST_DEVICE inline vc_aos::vector3 vector( - const vc_aos::transform3::matrix44& m, +/// @name Getter functions on @c algebra::vc_aos::matrix_type +/// @{ + +using cmath::element; + +/// Function extracting a slice from matrix44 - const +template class array_t, + typename value_t, std::size_t N, + std::enable_if_t = true> +ALGEBRA_HOST_DEVICE inline const auto& vector( + const storage::matrix44& m, std::size_t #ifndef NDEBUG row @@ -66,15 +72,20 @@ ALGEBRA_HOST_DEVICE inline vc_aos::vector3 vector( case 3: return m.t; default: +#ifndef _MSC_VER + __builtin_unreachable(); +#else return m.x; +#endif } } -/// Function extracting a slice from the matrix used by -/// @c algebra::vc_aos::transform3 -template = true> -ALGEBRA_HOST_DEVICE inline vc_aos::vector3 vector( - const vc_aos::transform3::matrix44& m, +/// Function extracting a slice from matrix44 - non-const +template class array_t, + typename value_t, std::size_t N, + std::enable_if_t = true> +ALGEBRA_HOST_DEVICE inline auto& vector( + storage::matrix44& m, std::size_t #ifndef NDEBUG row @@ -94,15 +105,14 @@ ALGEBRA_HOST_DEVICE inline vc_aos::vector3 vector( case 3: return m.t; default: +#ifndef _MSC_VER + __builtin_unreachable(); +#else return m.x; +#endif } } -/// @name Getter functions on @c algebra::vc_aos::matrix_type -/// @{ - -using cmath::element; - /// @} } // namespace getter diff --git a/frontend/vc_soa/CMakeLists.txt b/frontend/vc_soa/CMakeLists.txt index b6344424..d4980cca 100644 --- a/frontend/vc_soa/CMakeLists.txt +++ b/frontend/vc_soa/CMakeLists.txt @@ -9,6 +9,6 @@ algebra_add_library( algebra_vc_soa vc_soa "include/algebra/vc_soa.hpp" ) target_link_libraries( algebra_vc_soa INTERFACE algebra::common algebra::vc_soa_storage algebra::cmath_math - algebra::vc_soa_math ) + algebra::vc_soa_math algebra::vc_aos_math ) algebra_test_public_headers( algebra_vc_soa "algebra/vc_soa.hpp" ) diff --git a/frontend/vc_soa/include/algebra/vc_soa.hpp b/frontend/vc_soa/include/algebra/vc_soa.hpp index e89eb8aa..89a15ab6 100644 --- a/frontend/vc_soa/include/algebra/vc_soa.hpp +++ b/frontend/vc_soa/include/algebra/vc_soa.hpp @@ -1,6 +1,6 @@ /** Algebra plugins library, part of the ACTS project * - * (c) 2023 CERN for the benefit of the ACTS project + * (c) 2023-2024 CERN for the benefit of the ACTS project * * Mozilla Public License Version 2.0 */ @@ -8,6 +8,7 @@ #pragma once // Project include(s). +#include "algebra/math/impl/vc_aos_transform3.hpp" #include "algebra/math/vc_soa.hpp" #include "algebra/storage/vc_soa.hpp" @@ -32,7 +33,7 @@ namespace vc_soa { /// @{ template -using transform3 = math::transform3; +using transform3 = algebra::vc_aos::math::transform3; /// @} @@ -66,7 +67,8 @@ using vc_soa::math::normalize; } // namespace vector -namespace matrix { +// Produces clash with matrix typedefs in other plugins +/*namespace matrix { using size_type = vc_soa::size_type; @@ -76,6 +78,6 @@ using array_type = vc_soa::storage_type; template using matrix_type = vc_soa::matrix_type; -} // namespace matrix +}*/ // namespace matrix } // namespace algebra diff --git a/math/cmath/include/algebra/math/impl/cmath_getter.hpp b/math/cmath/include/algebra/math/impl/cmath_getter.hpp index 6d7b2199..ef0c31b5 100644 --- a/math/cmath/include/algebra/math/impl/cmath_getter.hpp +++ b/math/cmath/include/algebra/math/impl/cmath_getter.hpp @@ -23,7 +23,8 @@ namespace algebra::cmath { * @param v the input vector **/ template class array_t, - typename scalar_t, size_type N, std::enable_if_t= 2, bool> = true> + typename scalar_t, size_type N, + std::enable_if_t<(N >= 2) && std::is_scalar_v, bool> = true> ALGEBRA_HOST_DEVICE inline scalar_t phi( const array_t &v) noexcept { @@ -35,7 +36,8 @@ ALGEBRA_HOST_DEVICE inline scalar_t phi( * @param v the input vector **/ template class array_t, - typename scalar_t, size_type N, std::enable_if_t= 3, bool> = true> + typename scalar_t, size_type N, + std::enable_if_t<(N >= 3) && std::is_scalar_v, bool> = true> ALGEBRA_HOST_DEVICE inline scalar_t theta( const array_t &v) noexcept { @@ -48,7 +50,8 @@ ALGEBRA_HOST_DEVICE inline scalar_t theta( * @param v the input vector **/ template class array_t, - typename scalar_t, size_type N, std::enable_if_t= 2, bool> = true> + typename scalar_t, size_type N, + std::enable_if_t<(N >= 2) && std::is_scalar_v, bool> = true> ALGEBRA_HOST_DEVICE inline scalar_t perp( const array_t &v) noexcept { @@ -60,7 +63,8 @@ ALGEBRA_HOST_DEVICE inline scalar_t perp( * @param v the input vector **/ template class array_t, - typename scalar_t, size_type N, std::enable_if_t = true> + typename scalar_t, size_type N, + std::enable_if_t<(N == 2) && std::is_scalar_v, bool> = true> ALGEBRA_HOST_DEVICE inline scalar_t norm(const array_t &v) { return perp(v); @@ -71,7 +75,8 @@ ALGEBRA_HOST_DEVICE inline scalar_t norm(const array_t &v) { * @param v the input vector **/ template class array_t, - typename scalar_t, size_type N, std::enable_if_t= 3, bool> = true> + typename scalar_t, size_type N, + std::enable_if_t<(N >= 3) && std::is_scalar_v, bool> = true> ALGEBRA_HOST_DEVICE inline scalar_t norm(const array_t &v) { return algebra::math::sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); @@ -83,7 +88,8 @@ ALGEBRA_HOST_DEVICE inline scalar_t norm(const array_t &v) { * @param v the input vector **/ template class array_t, - typename scalar_t, size_type N, std::enable_if_t= 3, bool> = true> + typename scalar_t, size_type N, + std::enable_if_t<(N >= 3) && std::is_scalar_v, bool> = true> ALGEBRA_HOST_DEVICE inline scalar_t eta( const array_t &v) noexcept { diff --git a/math/vc_aos/CMakeLists.txt b/math/vc_aos/CMakeLists.txt index 64a723c7..8e6a63a9 100644 --- a/math/vc_aos/CMakeLists.txt +++ b/math/vc_aos/CMakeLists.txt @@ -11,7 +11,6 @@ algebra_add_library( algebra_vc_aos_math vc_aos_math "include/algebra/math/impl/vc_aos_transform3.hpp" "include/algebra/math/impl/vc_aos_vector.hpp" ) target_link_libraries( algebra_vc_aos_math - INTERFACE Vc::Vc algebra::common algebra::common_math algebra::vc_storage - algebra::cmath_math ) + INTERFACE Vc::Vc algebra::common algebra::common_math algebra::vc_storage ) algebra_test_public_headers( algebra_vc_aos_math "algebra/math/vc_aos.hpp" ) diff --git a/math/vc_aos/include/algebra/math/impl/vc_aos_transform3.hpp b/math/vc_aos/include/algebra/math/impl/vc_aos_transform3.hpp index d40f8ff8..be3eea06 100644 --- a/math/vc_aos/include/algebra/math/impl/vc_aos_transform3.hpp +++ b/math/vc_aos/include/algebra/math/impl/vc_aos_transform3.hpp @@ -8,9 +8,10 @@ #pragma once // Project include(s). -#include "algebra/math/cmath.hpp" -#include "algebra/math/impl/vc_aos_vector.hpp" +#include "algebra/math/common.hpp" #include "algebra/qualifiers.hpp" +#include "algebra/storage/matrix44.hpp" +#include "algebra/storage/vector.hpp" // Vc include(s). #ifdef _MSC_VER @@ -26,95 +27,46 @@ namespace algebra::vc_aos::math { -namespace internal { - -/// 4x4 matrix type used by @c algebra::vc_aos::math::transform3 -template -struct matrix44 { - - /// Equality operator between two matrices - bool operator==(const matrix44 &rhs) const { - return ((x == rhs.x).isFull() && (y == rhs.y).isFull() && - (z == rhs.z).isFull() && (t == rhs.t).isFull()); - } - - /// Data variables - Vc::SimdArray x, y, z, t; - -}; // struct matrix44 - -/// Functor used to access elements of Vc matrices -template