E.V.E
v2023.02.15
 
Loading...
Searching...
No Matches

◆ transform_reduce

eve::algo::transform_reduce = function_with_traits<transform_reduce_>[default_simple_algo_traits]
inlineconstexpr

#include <eve/module/algo/algo/transform_reduce.hpp>

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.

Supports fuse_operations trait => map_op starts to take an extra parameter: current sum. Allows to use fma. Note that add operations and zero are still used and have to be correct.

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

#include <eve/algo.hpp>

Callable Signatures

namespace eve::algo
{
template <eve::algo::relaxed_range Rng, typename MapOp, typename U>
U transform_reduce(Rng&& rng, MapOp map_op, U init); // 1
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); // 2
}
constexpr auto transform_reduce
SIMD version of std::transform_reduce for a single range.
Definition: transform_reduce.hpp:177
  1. 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.
  2. 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::add, eve::zero}.

Return value

  1. Sum of init and map_op applied on each element of rng.
  2. Generalized sum of init and map_op applied on each element of rng using add_zero.

Example

#include <eve/module/core.hpp>
#include <eve/module/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.f) = "
<< eve::algo::transform_reduce(v, [](auto x) { return x + x; }, 0.) << "\n";
std::cout << " -> std::transform_reduce(v.begin(), v.end(), std::plus<>{}, 0.f, [](auto x) { return x + x }) = "
<< std::transform_reduce(v.begin(), v.end(), 0., std::plus<>{}, [](auto x) { return x + x; }) << "\n";
std::cout << " -> eve::algo::reduce(eve::views::map(v, [](auto x) { return x + x }), 0.f) = "
<< eve::algo::reduce(eve::views::map(v, [](auto x) { return x + x; }), 0.f) << "\n";
std::cout << " -> eve::algo::transform_reduce(v, [](auto x) { return x + x }, std::pair{eve::mul, eve::one}, 1.f) = "
<< eve::algo::transform_reduce(v, [](auto x) { return x + x; }, std::pair{eve::mul, eve::one}, 1.f) << "\n";
std::cout << " -> eve::algo::transform_reduce[eve::algo::fuse_operations](v, [](auto x, auto sum) { return eve::fma(x, 2.f, sum); }, 0.f) = "
<< eve::algo::transform_reduce[eve::algo::fuse_operations](v, [](auto x, auto sum) { return eve::fma(x, .5f, sum); }, 0.f) << "\n";
}
constexpr auto fuse_operations
Some algorithms (for example transform_reduce) can be implemented more efficient if you fuse multiple...
Definition: traits.hpp:305
constexpr auto reduce
SIMD optimized version of std::reduce.
Definition: reduce.hpp:152
constexpr auto mul
tuple_callable` computing the product of its arguments.
Definition: mul.hpp:90
constexpr auto one
Computes the constant .
Definition: one.hpp:65
constexpr auto fma
strict_elementwise_callable computing the fused multiply add of its three parameters.
Definition: fma.hpp:83