QMCPACK
ParallelExecutor< TT > Class Template Reference

Abstraction for running concurrent tasks in parallel by an executor executor workers can be OpenMP threads, std::thread. More...

+ Collaboration diagram for ParallelExecutor< TT >:

Public Member Functions

template<typename F , typename... Args>
void operator() (int num_tasks, F &&f, Args &&... args)
 Concurrently execute an arbitrary function/kernel with task id and arbitrary args. More...
 
template<>
void operator() (int num_tasks, F &&f, Args &&... args)
 implements parallel tasks executed by threads in an OpenMP thread pool. More...
 
template<>
void operator() (int num_tasks, F &&f, Args &&... args)
 implements parallel tasks executed by STD threads. More...
 

Detailed Description

template<Executor TT = Executor::OPENMP>
class qmcplusplus::ParallelExecutor< TT >

Abstraction for running concurrent tasks in parallel by an executor executor workers can be OpenMP threads, std::thread.

Note: it is not related to the executor that C++ standard is working on currently.

Construct with num_tasks to run then call operator(F, args...) F is lambda or function with form void F(int task_id, args...) [](int task_id, args...){...}

This has not been tested for nested threading with openmp It is not intended for use below the top level of openmp threading.

Definition at line 35 of file ParallelExecutor.hpp.

Member Function Documentation

◆ operator()() [1/3]

void operator() ( int  num_tasks,
F &&  f,
Args &&...  args 
)

implements parallel tasks executed by threads in an OpenMP thread pool.

This specialization throws below the top openmp theading level exception must be caught at thread level or terminate is called.

Definition at line 37 of file ParallelExecutorOPENMP.hpp.

References omp_get_level().

38 {
39  const std::string nesting_error{"ParallelExecutor should not be used for nested openmp threading\n"};
40  if (omp_get_level() > 0)
41  throw std::runtime_error(nesting_error);
42  int nested_throw_count = 0;
43  int throw_count = 0;
44 #pragma omp parallel for reduction(+ : nested_throw_count, throw_count)
45  for (int task_id = 0; task_id < num_tasks; ++task_id)
46  {
47  try
48  {
49  f(task_id, std::forward<Args>(args)...);
50  }
51  catch (const std::runtime_error& re)
52  {
53  if (nesting_error == re.what())
54  ++nested_throw_count;
55  else
56  {
57  std::cerr << re.what() << std::flush;
58  ++throw_count;
59  }
60  }
61  catch (...)
62  {
63  ++throw_count;
64  }
65  }
66  if (throw_count > 0)
67  throw std::runtime_error("Unexpected exception thrown in threaded section");
68  else if (nested_throw_count > 0)
69  throw std::runtime_error(nesting_error);
70 }
omp_int_t omp_get_level()
Definition: OpenMP.h:28

◆ operator()() [2/3]

void operator() ( int  num_tasks,
F &&  f,
Args &&...  args 
)

Concurrently execute an arbitrary function/kernel with task id and arbitrary args.

ie each task will run f(int task_id, Args... args)

◆ operator()() [3/3]

void operator() ( int  num_tasks,
F &&  f,
Args &&...  args 
)

implements parallel tasks executed by STD threads.

One task one thread mapping.

Definition at line 50 of file ParallelExecutorSTD.hpp.

51 {
52  std::vector<std::thread> threads(num_tasks_);
53 
54  for (int task_id = 0; task_id < num_tasks; ++task_id)
55  {
56  threads[task_id] = std::thread(TaskWrapper<F>{std::forward<F>(f)}, task_id, std::forward<Args>(args)...);
57  }
58 
59  for (int task_id = 0; task_id < num_tasks; ++task_id)
60  {
61  threads[task_id].join();
62  }
63 }

The documentation for this class was generated from the following file: