Utopia 2
Framework for studying models of complex & adaptive systems.
Loading...
Searching...
No Matches
Functions
STL Algorithm Overloads

Overloads for selecting execution policies at runtime. More...

Collaboration diagram for STL Algorithm Overloads:

Functions

template<class InputIt , class OutputIt >
OutputIt std::copy (const Utopia::ExecPolicy policy, InputIt first, InputIt last, OutputIt d_first)
 Copy the input range to a new range.
 
template<class InputIt , class UnaryFunction >
void std::for_each (const Utopia::ExecPolicy policy, InputIt first, InputIt last, UnaryFunction f)
 Apply a function to a range.
 
template<class InputIt , class OutputIt , class UnaryOperation >
OutputIt std::transform (const Utopia::ExecPolicy policy, InputIt first1, InputIt last1, OutputIt d_first, UnaryOperation unary_op)
 Apply a unary operator to a range and store the result in a new range.
 
template<class InputIt1 , class InputIt2 , class OutputIt , class BinaryOperation >
OutputIt std::transform (const Utopia::ExecPolicy policy, InputIt1 first1, InputIt1 last1, InputIt2 first2, OutputIt d_first, BinaryOperation binary_op)
 Apply a binary operator to two ranges and store the result in a new range.
 

Detailed Description

Overloads for selecting execution policies at runtime.

These algorithms are overloads of the respective STL algorithms where the ExecutionPolicy template parameter has been replaced by the Utopia::ExecPolicy runtime parameter. Developers can use these overloads to have the Utopia Parallel Facilities decide the actual execution policy at runtime. This is done by inserting the algorithm into the Utopia::exec_parallel function.

Using these overloads, developers still have to take care of potential data races, as if they are always executed with the intended execution policy.

How to add more algorithms

To add another algorithm overload, have a look at the original algorithm signature. A list of STL algorithms can be found here. Copy the signature including the ExecutionPolicy. Remove the ExecutionPolicy template parameter and replace the ExecutionPolicy argument with Utopia::ExecPolicy. Inside the function, call Utopia::exec_parallel with the Utopia::ExecPolicy as first argument. The second argument is a generic lambda which captures nothing ([]) and takes a single generic argument which will be a tuple containing the algorithm's arguments (auto&& args_tpl). In the lambda body, create a localized version of your STL algorithm which simply takes a list of arguments and calls the STL algorithm. Depending on the algorithm return type, make sure to return the STL algorithm return value. Finally, add the other arguments of the algorithm overload to the call to Utopia::exec_parallel.

The result looks weird, but wrapping the arguments inside a tuple relieves us from writing different code for the case where std::execution is not defined.

Example:

// Inject into STL namespace for true overload
namespace std {
// Same template signature as sequential `do_stuff`, plus exec policy
template<class InputIt, class OutputIt>
OutputIt
do_stuff(const Utopia::ExecPolicy policy, // <-- Runtime policy
InputIt first,
InputIt last,
OutputIt d_first)
{
policy, // <-- Runtime policy passed to this function
[](auto&& args_tpl) { // <-- Arguments wrapped into a tuple
// Create localized version of algorithm for use in std::apply
auto do_stuff = [](auto&&... args) {
return std::do_stuff(args...);
};
// Call the algorithm with the arguments packed into the tuple
// NOTE: Thanks to the `args_tpl` tuple, this call handles
// cases with varying numbers of arguments and in
// particular, the case where `std::execution` is not
// defined!
return std::apply(do_stuff, args_tpl);
},
// Now add the arguments that will be packed into the tuple
first,
last,
d_first);
}
} // namespace std
auto exec_parallel(MAYBE_UNUSED const Utopia::ExecPolicy policy, Func &&f, Args &&... args)
Call a function with an STL execution policy and arguments.
Definition parallel.hh:205
ExecPolicy
Runtime execution policies.
Definition parallel.hh:60
Definition parallel.hh:235

Function Documentation

◆ copy()

template<class InputIt , class OutputIt >
OutputIt std::copy ( const Utopia::ExecPolicy  policy,
InputIt  first,
InputIt  last,
OutputIt  d_first 
)

Copy the input range to a new range.

See https://en.cppreference.com/w/cpp/algorithm/copy

328{
330 policy,
331 [](auto&& args_tpl) {
332 auto copy = [](auto&&... args){ return std::copy(args...); };
333 return std::apply(copy, args_tpl);
334 },
335 first,
336 last,
337 d_first);
338}
OutputIt copy(const Utopia::ExecPolicy policy, InputIt first, InputIt last, OutputIt d_first)
Copy the input range to a new range.
Definition parallel.hh:324

◆ for_each()

template<class InputIt , class UnaryFunction >
void std::for_each ( const Utopia::ExecPolicy  policy,
InputIt  first,
InputIt  last,
UnaryFunction  f 
)

Apply a function to a range.

See https://en.cppreference.com/w/cpp/algorithm/for_each

350{
352 policy,
353 [](auto&& args_tpl) {
354 auto for_each = [](auto&&... args){ std::for_each(args...); };
355 std::apply(for_each, args_tpl);
356 },
357 first,
358 last,
359 f);
360}
void for_each(const Utopia::ExecPolicy policy, InputIt first, InputIt last, UnaryFunction f)
Apply a function to a range.
Definition parallel.hh:346

◆ transform() [1/2]

template<class InputIt , class OutputIt , class UnaryOperation >
OutputIt std::transform ( const Utopia::ExecPolicy  policy,
InputIt  first1,
InputIt  last1,
OutputIt  d_first,
UnaryOperation  unary_op 
)

Apply a unary operator to a range and store the result in a new range.

See https://en.cppreference.com/w/cpp/algorithm/transform

373{
375 policy,
376 [](auto&& args_tpl) {
377 auto transform = [](auto&&... args) {
378 return std::transform(args...);
379 };
380 return std::apply(transform, args_tpl);
381 },
382 first1,
383 last1,
384 d_first,
385 unary_op);
386}
OutputIt transform(const Utopia::ExecPolicy policy, InputIt first1, InputIt last1, OutputIt d_first, UnaryOperation unary_op)
Apply a unary operator to a range and store the result in a new range.
Definition parallel.hh:368

◆ transform() [2/2]

template<class InputIt1 , class InputIt2 , class OutputIt , class BinaryOperation >
OutputIt std::transform ( const Utopia::ExecPolicy  policy,
InputIt1  first1,
InputIt1  last1,
InputIt2  first2,
OutputIt  d_first,
BinaryOperation  binary_op 
)

Apply a binary operator to two ranges and store the result in a new range.

See https://en.cppreference.com/w/cpp/algorithm/transform

400{
402 policy,
403 [](auto&& args_tpl) {
404 auto transform = [](auto&&... args) {
405 return std::transform(args...);
406 };
407 return std::apply(transform, args_tpl);
408 },
409 first1,
410 last1,
411 first2,
412 d_first,
413 binary_op);
414}