Skip to content

Commit

Permalink
Add libm benchmarks
Browse files Browse the repository at this point in the history
Extended current benchmark tool with support to benchmark of libm
functions. Libm benchmark is enabled in all functions listed in
benchlibm.cpp.
It interfaces with the rest of the existing tool through
benchmark_callers_libm.hpp (defines macros which simplify how the
list of functions to benchmark looks like as it groups functions
by precision/accuracy/variant).
The tool is integrated with SLEEF via CMake, meaning it can
be built automatically when SLEEF is built. To enable that,
pass CMake argument -DSLEEF_BUILD_BENCH=ON and
-DSLEEF_BUILD_BENCH_REF=ON.
Note this option is only enabled on Linux OS.
  • Loading branch information
joanaxcruz committed Dec 23, 2024
1 parent b56eab1 commit 0633394
Show file tree
Hide file tree
Showing 9 changed files with 182 additions and 10 deletions.
10 changes: 10 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ option(SLEEF_BUILD_GNUABI_LIBS "libsleefgnuabi will be built." ON)
option(SLEEF_BUILD_SCALAR_LIB "libsleefscalar will be built." OFF)
option(SLEEF_BUILD_TESTS "Tests will be built." ON)
option(SLEEF_BUILD_BENCH "Bench will be built." OFF)
option(SLEEF_BUILD_BENCH_REF "Benchmark script for reference (e.g. system libm) will be built." OFF)
option(SLEEF_BUILD_INLINE_HEADERS "Build header for inlining whole SLEEF functions" OFF)

option(SLEEF_TEST_ALL_IUT "Perform tests on implementations with all vector extensions" OFF)
Expand Down Expand Up @@ -42,6 +43,15 @@ if (SLEEF_BUILD_BENCH)
set(SLEEF_ENABLE_CXX ON)
endif ()

if (SLEEF_BUILD_BENCH_REF)
if (NOT SLEEF_BUILD_BENCH)
message(FATAL_ERROR "SLEEF_BUILD_BENCH must be on when SLEEF_BUILD_BENCH_REF is enabled.")
endif ()
if(NOT CMAKE_SYSTEM_NAME MATCHES Linux)
message(FATAL_ERROR "Libm benchmarking not supported in this OS.")
endif()
endif ()

if (DEFINED SLEEF_BUILD_SHARED_LIBS)
set(BUILD_SHARED_LIBS ${SLEEF_BUILD_SHARED_LIBS})
endif ()
Expand Down
11 changes: 10 additions & 1 deletion docs/4-tools/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,4 +153,13 @@ executables may be built (according to feature detection):
These will benchmark 256bit and 512bit vector implementations
for vector functions respectively.
Note these executables can also be used to benchmark scalar
functions.
functions.

<h3 id="benchmark">Benchmarking libm</h3>
This tool can also benchmark libm functions listed in
`benchlibm.cpp`.
To enable this, pass on extra build option `-DSLEEF_BUILD_BENCH_REF=ON`
(on top of `-DSLEEF_BUILD_BENCH` from before).
This will produce a new script `./build/bin/benchlibm128`.
You can interact with this in a similar fashion as described for
`./build/bin/benchsleef128`.
24 changes: 16 additions & 8 deletions src/libm-benchmarks/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,27 +25,35 @@ link_directories(${sleef_BINARY_DIR}/lib) # libsleef


set(EXTRA_CFLAGS -Wall -O2 -Wno-attributes)
set(BENCH_SRC_FILE "benchsleef.cpp" "benchmark_callers.hpp" "benchmark_templates.hpp" "gen_input.hpp" "type_defs.hpp")
set(BENCH_HPP_SRC_FILES "benchmark_callers.hpp" "benchmark_templates.hpp" "gen_input.hpp" "type_defs.hpp")
set(BENCH_PROPERTIES C_STANDARD 99 CXX_STANDARD 17)
set(BENCH_LIBS benchmark sleef Threads::Threads) # Link Google Benchmark and sleef to the project
set(GOOGLE_BENCH_LIBS benchmark Threads::Threads) # Link Google Benchmark to the project

# Add source to this project's executable.
add_executable (benchsleef128 ${BENCH_SRC_FILE})
add_executable (benchsleef128 "benchsleef.cpp" ${BENCH_HPP_SRC_FILES})
set_target_properties(benchsleef128 PROPERTIES ${BENCH_PROPERTIES})
target_compile_options(benchsleef128 PRIVATE ${EXTRA_CFLAGS} -march=native)
target_link_libraries(benchsleef128 ${BENCH_LIBS})
target_link_libraries(benchsleef128 sleef ${GOOGLE_BENCH_LIBS})
add_dependencies(benchsleef128 googlebenchmark)

if(SLEEF_BUILD_BENCH_REF)
add_executable (benchlibm128 "benchlibm.cpp" ${BENCH_HPP_SRC_FILES})
set_target_properties(benchlibm128 PROPERTIES ${BENCH_PROPERTIES})
target_compile_options(benchlibm128 PRIVATE ${EXTRA_CFLAGS} -march=native "-DBENCH_LIBM")
target_link_libraries(benchlibm128 ${GOOGLE_BENCH_LIBS})
add_dependencies(benchlibm128 googlebenchmark)
endif()

if(CMAKE_SYSTEM_PROCESSOR MATCHES "(x86)|(X86)|(amd64)|(AMD64)")
add_executable (benchsleef256 ${BENCH_SRC_FILE})
add_executable (benchsleef256 "benchsleef.cpp" ${BENCH_HPP_SRC_FILES})
set_target_properties(benchsleef256 PROPERTIES ${BENCH_PROPERTIES})
target_compile_options(benchsleef256 PRIVATE ${EXTRA_CFLAGS} "-march=native" "-DARCH_VECT_LEN=256")
target_link_libraries(benchsleef256 ${BENCH_LIBS})
target_link_libraries(benchsleef256 sleef ${GOOGLE_BENCH_LIBS})
add_dependencies(benchsleef256 googlebenchmark)

add_executable (benchsleef512 ${BENCH_SRC_FILE})
add_executable (benchsleef512 "benchsleef.cpp" ${BENCH_HPP_SRC_FILES})
set_target_properties(benchsleef512 PROPERTIES ${BENCH_PROPERTIES})
target_compile_options(benchsleef512 PRIVATE ${EXTRA_CFLAGS} "-mavx512f" "-DARCH_VECT_LEN=512")
target_link_libraries(benchsleef512 ${BENCH_LIBS})
target_link_libraries(benchsleef512 sleef ${GOOGLE_BENCH_LIBS})
add_dependencies(benchsleef512 googlebenchmark)
endif()
9 changes: 9 additions & 0 deletions src/libm-benchmarks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,15 @@ for vector functions respectively.
Note these executables can also be used to benchmark scalar
functions.

<h3 id="benchmark">Benchmarking libm</h3>
This tool can also benchmark libm functions listed in
`benchlibm.cpp`.
To enable this, pass on extra build option `-DSLEEF_BUILD_BENCH_REF=ON`
(on top of `-DSLEEF_BUILD_BENCH` from before).
This will produce a new script `./build/bin/benchlibm128`.
You can interact with this in a similar fashion as described for
`./build/bin/benchsleef128`.

<h3 id="benchmark">Maintenance</h3>
Some functions are still not enabled in the benchmarks.
In order to add a function which uses the types already
Expand Down
69 changes: 69 additions & 0 deletions src/libm-benchmarks/benchlibm.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Copyright Naoki Shibata and contributors 2024.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

#include "benchmark_callers_libm.hpp"
#include <math.h>

// ======================TRIG==========================
// sin on different intervals
BENCH_SCALAR(sin, 0, 6.28);
BENCH_SCALAR(sin, 0, 1e+6);
BENCH_SINGLE_SCALAR(sin, 0, 1e20);
BENCH_DOUBLE_SCALAR(sin, 0, 1e+100);

// cos on different intervals
BENCH_SCALAR(cos, 0, 6.28);
BENCH_SCALAR(cos, 0, 1e+6);
BENCH_SINGLE_SCALAR(cos, 0, 1e20);
BENCH_DOUBLE_SCALAR(cos, 0, 1e+100);

// tan on different intervals
BENCH_SCALAR(tan, 0, 6.28);
BENCH_SCALAR(tan, 0, 1e+6);
BENCH_SINGLE_SCALAR(tan, 0, 1e20);
BENCH_DOUBLE_SCALAR(tan, 0, 1e+100);

BENCH_SCALAR_VOID_3ARGS(sincos, 0, 6.28);
BENCH_SCALAR_VOID_3ARGS(sincos, 0, 1e+6);
BENCH_SINGLE_SCALAR_VOID_3ARGS(sincos, 0, 1e20);
BENCH_DOUBLE_SCALAR_VOID_3ARGS(sincos, 0, 1e+100);

// inverse trig
BENCH_SCALAR(asin, -1.0, 1.0);
BENCH_SCALAR(acos, -1.0, 1.0);
BENCH_SCALAR(atan, -10, 10);
BENCH_SCALAR_2ARGS(atan2, -10, 10)

// ======================NON TRIG==========================
// log
BENCH_SINGLE_SCALAR(log, 0, 1e+38);
BENCH_DOUBLE_SCALAR(log, 0, 1e+100);

BENCH_SINGLE_SCALAR(log2, 0, 1e+38);
BENCH_DOUBLE_SCALAR(log2, 0, 1e+100);

BENCH_SINGLE_SCALAR(log10, 0, 1e+38);
BENCH_DOUBLE_SCALAR(log10, 0, 1e+100);

BENCH_SINGLE_SCALAR(log1p, 0, 1e+38);
BENCH_DOUBLE_SCALAR(log1p, 0, 1e+100);

// exp
BENCH_SINGLE_SCALAR(exp, -700, 700);
BENCH_DOUBLE_SCALAR(exp, -700, 700);

BENCH_SINGLE_SCALAR(exp2, -100, 100);
BENCH_DOUBLE_SCALAR(exp2, -700, 700);

BENCH_SINGLE_SCALAR(exp10, -100, 100);
BENCH_DOUBLE_SCALAR(exp10, -700, 700);

BENCH_SINGLE_SCALAR(expm1, -100, 100);
BENCH_DOUBLE_SCALAR(expm1, -700, 700);

// pow
BENCH_SCALAR_2ARGS(pow, -30, 30);

BENCHMARK_MAIN();
46 changes: 46 additions & 0 deletions src/libm-benchmarks/benchmark_callers_libm.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright Naoki Shibata and contributors 2024.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

#pragma once
#include "benchmark_templates.hpp"

// Callers for libm - no separate file as its much simpler
// only interested in scalar (i think?)
#define BENCH(funname, funtype, namefilter, min, max) \
BENCHMARK_CAPTURE(BM_Sleef_templated_function, #funname, funtype funname, min, max) \
->Name("MB_libm_" #funname "_" #namefilter "_" #min "_" #max);

#define BENCH_SINGLE_SCALAR(fun, min, max) \
BENCH(fun, (float (*) (float)), u10_scalarf, min, max);
#define BENCH_DOUBLE_SCALAR(fun, min, max) \
BENCH(fun, (double (*) (double)), u10_scalard, min, max);

#define BENCH_SCALAR(fun, min, max) \
BENCH_SINGLE_SCALAR(fun, min, max); \
BENCH_DOUBLE_SCALAR(fun, min, max);

// special case for pow and atan2
#define BENCH_SINGLE_SCALAR_2ARGS(fun, min, max) \
BENCH(fun, (float (*) (float, float)), u10_scalarf, min, max);
#define BENCH_DOUBLE_SCALAR_2ARGS(fun, min, max) \
BENCH(fun, (double (*) (double, double)), u10_scalard, min, max);

#define BENCH_SCALAR_2ARGS(fun, min, max) \
BENCH_SINGLE_SCALAR_2ARGS(fun, min, max); \
BENCH_DOUBLE_SCALAR_2ARGS(fun, min, max);


// special case for sincos
#define BENCH_SINGLE_SCALAR_VOID_3ARGS(fun, min, max) \
BENCH(fun, (void (*)(float, float*, float*)), u10_scalarf, min, max);
#define BENCH_DOUBLE_SCALAR_VOID_3ARGS(fun, min, max) \
BENCH(fun, (void (*)(double, double*, double*)), u10_scalard, min, max);

#define BENCH_SCALAR_VOID_3ARGS(fun, min, max) \
BENCH_SINGLE_SCALAR_VOID_3ARGS(fun, min, max); \
BENCH_DOUBLE_SCALAR_VOID_3ARGS(fun, min, max);



16 changes: 16 additions & 0 deletions src/libm-benchmarks/benchmark_templates.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,19 @@ static void BM_Sleef_templated_function(benchmark::State &state,
benchmark::Counter(num_els_processed, benchmark::Counter::kIsRate |
benchmark::Counter::kInvert);
}

// Necessary for libm sincos (which takes 3 arguments)
template <typename T>
static void BM_Sleef_templated_function(benchmark::State &state,
void (*fun)(T, T*, T*), double min,
double max) {
T p0, p1;
T x = gen_input<T>(min, max);
for (auto _ : state) {
call_fun(fun, x, &p0, &p1);
}
int num_els_processed = state.iterations() * vector_len<T>;
state.counters["NSperEl"] =
benchmark::Counter(num_els_processed, benchmark::Counter::kIsRate |
benchmark::Counter::kInvert);
}
1 change: 1 addition & 0 deletions src/libm-benchmarks/gen_input.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#pragma once
#include "type_defs.hpp"
#include <algorithm>
#include <cstdint>
#include <vector>

///////////////////////////////////
Expand Down
6 changes: 5 additions & 1 deletion src/libm-benchmarks/type_defs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
// http://www.boost.org/LICENSE_1_0.txt)

#pragma once
#include <sleef.h>

///////////////////////////////////
// Library Includes and ///////////
Expand All @@ -14,6 +13,9 @@ template <typename T> const inline int vector_len = 1;
template <> const inline int vector_len<float> = 1;
template <> const inline int vector_len<double> = 1;

#if !defined(BENCH_LIBM)

#include <sleef.h>
#if defined(__i386__) || defined(__x86_64__)
#if defined(_MSC_VER)
#include <intrin.h>
Expand Down Expand Up @@ -93,4 +95,6 @@ typedef svfloat32x2_t svfloat2;
template <> const inline int vector_len<svfloat> = svcntw();
template <> const inline int vector_len<svdouble> = svcntd();
#define ENABLE_SVECTOR_BENCHMARKS
#endif

#endif

0 comments on commit 0633394

Please sign in to comment.