#include <eve/algo/transform_reduce.hpp>
SIMD version of std::transform_reduce for a single range.
Configurable Callable Object performing a SIMD optimized version of the transform_reduce By default, the operation will be unrolled by a factor of 4, align memory accesses and perform conversions if needed.
Due to the nature of how SIMD algorithms work, the reduce operation has to be paired with its, neutral element. For example, for add you pass {add, zero}
as zero is the identity for add. Instead of zero it can be beneficial to pass eve's constants like eve::zero
, eve::one
because sometimes the implementation can be improved
- Note
- The interface differs from the standard because we felt this better matches our use case: do unary transformation and then accumulate that.
- Multiple range interface is omitted for simplicity. Use eve::zip to get that effect.
- eve::transform_reduce requires less requirement on the operations than eve::views::map. In transform_reduce we don't need the map_op to be a template, for example.
- Compilers can auto-vectorize reductions, especially with special options. Maybe you don't need a library implementation.
Alternative Header
namespace eve::algo
{
template <eve::algo::relaxed_range Rng, typename MapOp, typename U>
template< eve::algo::relaxed_range Rng, typename MapOp
, typename AddOp, typename Zero, typename U
>
U
transform_reduce(Rng&& rng, MapOp map_op, std::pair<AddOp, Zero> add_zero, U init);
}
constexpr auto transform_reduce
SIMD version of std::transform_reduce for a single range.
Definition: transform_reduce.hpp:167
- Applies
map_op
to each element in the range rng
and reduces the results along with the initial value init
using regular addition as the reduce operation.
- Applies
map_op
to each element in the range rng
and reduces the results along with the initial value init
using the add_zero
reduce operation and neutral element.
Parameters
rng
: Relaxed input range to process
init
: Initial value. Also type of init matches the result type
map_op
: Transformation operation
add_zero
: Pair of reduction operation (commutative/associative) and an identity (zero) for it. Default add_zero is {eve::plus, eve::zero}
.
Return value
- Sum of
init
and map_op
applied on each element of rng
.
- Generalized sum of
init
and map_op
applied on each element of rng
using add_zero
.
#include <eve/module/core.hpp>
#include <eve/algo.hpp>
#include <tts/tts.hpp>
#include <iostream>
#include <numeric>
#include <vector>
int main()
{
std::vector<float> v = {1.0f, 2.0f, 3.0f, 4.0f};
std::cout << " -> v = "
<< tts::as_string(v)
<< "\n";
std::cout << " -> eve::algo::transform_reduce(v, [](auto x) { return x + x }, 0.) = "
std::cout << " -> std::transform_reduce(v.begin(), v.end(), std::plus<>{}, 0., [](auto x) { return x + x }) = "
std::cout << " -> eve::algo::reduce(eve::views::map(v, [](auto x) { return x + x }), 0.) = "
std::cout << " -> eve::algo::transform_reduce(v, [](auto x) { return x + x }, std::pair{eve::mul, eve::one}, 0.) = "
}
constexpr auto reduce
SIMD optimized version of std::reduce.
Definition: reduce.hpp:152
constexpr callable_mul_ mul
Computes the sum of its arguments.
Definition: mul.hpp:83
constexpr callable_one_ one
Computes the constant .
Definition: one.hpp:51
struct eve::algo::views::@6 map
Given a relaxed iterator/range and an operation return relaxed iterator/range that has no store and a...