Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add transform benchmarks
  • Loading branch information
AntoinePrv committed Sep 14, 2026
commit 3de529db4137361ee33001ee0c6df79ec6eea112
26 changes: 20 additions & 6 deletions benchmark/bench_math.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,29 @@ namespace
static_cast<std::int64_t>(state.iterations() * size * 2 * sizeof(input_t)));
}

template <typename Op, typename Alloc, alignment aligned = alignment{}>
void bench_simd(benchmark::State& state)
template <typename Op, typename Alloc, alignment aligned = alignment {}>
void bench_map_unary(benchmark::State& state)
{
bench_unary<Op, Alloc>(
state,
[](auto in, auto out)
{ Op::template apply_range_simd<aligned>(in, out); });
{ Op::template range_apply_map_unary<aligned>(in, out); });
}

template <typename Op, typename Alloc>
void bench_transform(benchmark::State& state)
{
bench_unary<Op, Alloc>(
state,
[](auto in, auto out)
{ Op::template range_apply_transform(in, out); });
}

template <typename Op, typename Alloc>
void bench_scalar(benchmark::State& state)
{
bench_unary<Op, Alloc>(state, [](auto in, auto out)
{ Op::apply_range_scalar(in, out); });
{ Op::range_apply_scalar(in, out); });
}

template <typename Op, typename Bench>
Expand All @@ -77,9 +86,14 @@ namespace
using aligned_alloc = typename xsimd::test::aligned_vector<input_t>::allocator_type;
using unaligned_alloc = typename xsimd::test::unaligned_vector<input_t>::allocator_type;

// To avoid an explosion of benchmarks, we probagly want to only benchmark aligned for
// math ops, and benchmark map_unary/transform setups (alignment...) separately on a
// few ops.
register_bench<Op>("scalar/aligned", bench_scalar<Op, aligned_alloc>);
register_bench<Op>("simd/aligned", bench_simd<Op, aligned_alloc, alignment { .start_aligned = true }>);
register_bench<Op>("simd/unaligned", bench_simd<Op, unaligned_alloc>);
register_bench<Op>("simd-map/aligned", bench_map_unary<Op, aligned_alloc, alignment { .start_aligned = true }>);
register_bench<Op>("simd-map/unaligned", bench_map_unary<Op, unaligned_alloc>);
register_bench<Op>("simd-transform/aligned", bench_map_unary<Op, aligned_alloc>);
register_bench<Op>("simd-transform/unaligned", bench_map_unary<Op, unaligned_alloc>);
}

bool const registered = []
Expand Down
2 changes: 1 addition & 1 deletion include/xsimd_algorithm/stl/transform.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#include <iterator>
#include <type_traits>

#include "xsimd/xsimd.hpp"
#include <xsimd/xsimd.hpp>

namespace xsimd
{
Expand Down
18 changes: 13 additions & 5 deletions test-utils/include/xsimd_test_utils/map_unary_data.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/

#ifndef XSIMD_ALGORITHM_TEST_UTILS_MAP_UNARY_DATA_HPP
#define XSIMD_ALGORITHM_TEST_UTILS_MAP_UNARY_DATA_HPP
#ifndef XSIMD_ALGORITHM_TEST_UTILS_MATH_DATA_HPP
#define XSIMD_ALGORITHM_TEST_UTILS_MATH_DATA_HPP

#include <cmath>
#include <cstddef>
Expand All @@ -17,6 +17,7 @@
#include <vector>

#include "xsimd_algorithm/builder.hpp"
#include "xsimd_algorithm/stl/transform.hpp"

#include "xsimd_test_utils/utils.hpp"

Expand All @@ -33,23 +34,30 @@ namespace xsimd::test
template <typename Alloc>
using output_allocator = typename std::allocator_traits<Alloc>::template rebind_alloc<output_t>;

static void apply_range_scalar(std::span<input_t const> in, std::span<output_t> out)
static void range_apply_scalar(std::span<input_t const> in, std::span<output_t> out)
{
for (std::size_t i = 0; i < in.size(); ++i)
{
out[i] = Derived::apply_scalar(in[i]);
}
}

template <xsimd::builder::alignment aligned = xsimd::builder::alignment{}>
static void apply_range_simd(std::span<input_t const> in, std::span<output_t> out)
template <xsimd::builder::alignment aligned = xsimd::builder::alignment {}>
static void range_apply_map_unary(std::span<input_t const> in, std::span<output_t> out)
{
constexpr builder::unary_options opts = { .unroll_factor = 4, .pure = Derived::pure };
return xsimd::builder::map_unary<aligned, opts>(
in, out, [](auto x)
{ return Derived::apply_batch(x); });
}

inline static void range_apply_transform(std::span<input_t const> in, std::span<output_t> out)
{
return xsimd::transform(
in.data(), in.data() + in.size(), out.data(), [](auto x)
{ return Derived::apply_batch(x); });
}

template <typename Alloc>
static auto make_input_output(std::size_t size)
-> std::pair<std::vector<input_t, Alloc>, std::vector<output_t, output_allocator<Alloc>>>
Expand Down
4 changes: 2 additions & 2 deletions test/test_math.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@

namespace
{
template <typename Op, typename Alloc, xsimd::builder::alignment aligned = xsimd::builder::alignment{}>
template <typename Op, typename Alloc, xsimd::builder::alignment aligned = xsimd::builder::alignment {}>
void check_unary_math()
{
// Not a multiple of the batch size, to exercise the tail.
constexpr std::size_t test_size = 94;

auto [input, output] = Op::template make_input_output<Alloc>(test_size);

Op::template apply_range_simd<aligned>(xsimd::test::as_span(input), xsimd::test::as_span(output));
Op::template range_apply_map_unary<aligned>(xsimd::test::as_span(input), xsimd::test::as_span(output));

for (std::size_t i = 0; i < input.size(); ++i)
{
Expand Down