Utopia 2
Framework for studying models of complex & adaptive systems.
Loading...
Searching...
No Matches
parallel.hh
Go to the documentation of this file.
1#ifndef UTOPIA_CORE_PARALLEL_HH
2#define UTOPIA_CORE_PARALLEL_HH
3
4// Include one of the available headers, preferring the external one
5#if defined(HAVE_ONEDPL)
6#include <oneapi/dpl/execution>
7#include <oneapi/dpl/algorithm>
8#elif defined(USE_INTERNAL_PSTL)
9#include <execution>
10#endif
11
12// PSTL is available
13#if defined(HAVE_ONEDPL) || defined(USE_INTERNAL_PSTL)
14#define HAVE_PSTL
15#endif
16
17// PSTL is available and parallelism is enabled
18#if defined(HAVE_PSTL) && defined(ENABLE_PARALLEL_STL)
19#define UTOPIA_PARALLEL // Now we're cookin'!
20#define MAYBE_UNUSED // Make sure to get proper warnings for unused parameter
21
22// Inject oneDPL execution policies into std namespace to have agnostic client
23// code
24#if defined(HAVE_ONEDPL)
25namespace std::execution {
26 using namespace oneapi::dpl::execution;
27}
28#endif
29
30#else
31#define MAYBE_UNUSED [[maybe_unused]] // Avoid warning for unused parameter
32#endif
33
34#include <algorithm>
35#include <exception>
36#include <tuple>
37
40
41namespace Utopia
42{
43
50
71
73
78{
79private:
81 inline static bool _enabled = false;
82
84
88 static std::shared_ptr<spdlog::logger> get_logger()
89 {
90 const auto log = spdlog::get(Utopia::log_core);
91 if (not log)
92 {
93 throw std::runtime_error("Cannot fetch core logger!");
94 }
95
96 return log;
97 }
98
99public:
102 {
104 disabled
105 };
106
108
113 static void init(const DataIO::Config& cfg)
114 {
115 bool setting = false;
116
117 // Try fetching settings on parallel execution
118 if (const YAML::Node& cfg_par = cfg["parallel_execution"])
119 {
120 setting = get_as<bool>("enabled", cfg_par);
121 }
122
123 if (setting)
125 else
127 }
128
130
135 static void set(const Setting value)
136 {
137 _enabled = (value == Setting::enabled);
138
139 const auto log = get_logger();
140 std::string msg = fmt::format("Parallel execution {}",
141 _enabled ? "enabled" : "disabled");
142
143#ifdef UTOPIA_PARALLEL
144 log->info(msg);
145#else
146 msg += ", but settings do NOT apply";
147 if (_enabled)
148 log->warn(msg);
149 else
150 log->debug(msg);
151#endif
152 }
153
155
160 static bool is_enabled() { return _enabled; }
161
163
167 static bool is_applied()
168 {
169#ifdef UTOPIA_PARALLEL
170 return _enabled;
171#else
172 return false;
173#endif
174 }
175};
176
178
203template<class Func, class... Args>
204auto
206 Func&& f,
207 Args&&... args)
208{
209#ifdef UTOPIA_PARALLEL
211 {
213 return f(std::forward_as_tuple(std::execution::unseq, args...));
215 return f(std::forward_as_tuple(std::execution::par, args...));
217 return f(std::forward_as_tuple(std::execution::par_unseq, args...));
218 }
219#endif
220
221#ifdef HAVE_PSTL
222 return f(std::forward_as_tuple(std::execution::seq, args...));
223#else
224 return f(std::forward_as_tuple(args...));
225#endif
226}
227
232} // namespace Utopia
233
234namespace std
235{
236
319
322template<class InputIt, class OutputIt>
323OutputIt
325 InputIt first,
326 InputIt last,
327 OutputIt d_first)
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}
339
341
344template<class InputIt, class UnaryFunction>
345void
347 InputIt first,
348 InputIt last,
349 UnaryFunction f)
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}
361
363
366template<class InputIt, class OutputIt, class UnaryOperation>
367OutputIt
369 InputIt first1,
370 InputIt last1,
371 OutputIt d_first,
372 UnaryOperation unary_op)
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}
387
389
392template<class InputIt1, class InputIt2, class OutputIt, class BinaryOperation>
393OutputIt
395 InputIt1 first1,
396 InputIt1 last1,
397 InputIt2 first2,
398 OutputIt d_first,
399 BinaryOperation binary_op)
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}
415
420} // namespace std
421
422#endif // UTOPIA_CORE_PARALLEL_HH
Static information on the status of parallel execution.
Definition parallel.hh:78
static bool is_enabled()
Query if parallel execution is currently enabled.
Definition parallel.hh:160
static std::shared_ptr< spdlog::logger > get_logger()
Fetch the core logger.
Definition parallel.hh:88
static bool is_applied()
Actually check if parallel features are applied at runtime.
Definition parallel.hh:167
static bool _enabled
Runtime setting for parallel execution.
Definition parallel.hh:81
static void init(const DataIO::Config &cfg)
Initialize parallel features based on configuration setting.
Definition parallel.hh:113
static void set(const Setting value)
Choose a setting for parallel execution at runtime.
Definition parallel.hh:135
Setting
Possible settings for parallel execution.
Definition parallel.hh:102
@ enabled
Enable parallel execution.
Definition parallel.hh:103
@ disabled
Disable parallel execution.
Definition parallel.hh:104
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
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
void for_each(const Utopia::ExecPolicy policy, InputIt first, InputIt last, UnaryFunction f)
Apply a function to a range.
Definition parallel.hh:346
YAML::Node Config
Type of a variadic dictionary-like data structure used throughout Utopia.
Definition types.hh:71
Container select_entities(const Manager &mngr, const DataIO::Config &sel_cfg)
Select entities according to parameters specified in a configuration.
Definition select.hh:213
const std::string log_core
Definition logging.hh:18
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
@ seq
Sequential (i.e., regular) execution.
Definition parallel.hh:66
@ unseq
SIMD execution on single thread.
Definition parallel.hh:67
@ par_unseq
SIMD execution on multiple threads.
Definition parallel.hh:69
@ par
Parallel/multithreaded execution.
Definition parallel.hh:68
Definition agent.hh:11
Definition parallel.hh:235
#define MAYBE_UNUSED
Definition parallel.hh:31