Mantid
Loading...
Searching...
No Matches
MultiThreaded.h
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
7#pragma once
8
9#include <atomic>
10#include <mutex>
11
12namespace Mantid {
13namespace Kernel {
14
21template <typename Arg>
22inline typename std::enable_if<std::is_pointer<Arg>::value, bool>::type threadSafe(Arg workspace) {
23 return !workspace || workspace->threadSafe();
24}
25
33template <typename Arg, typename... Args>
34inline typename std::enable_if<std::is_pointer<Arg>::value, bool>::type threadSafe(Arg workspace, Args &&...others) {
35 return (!workspace || workspace->threadSafe()) && threadSafe(std::forward<Args>(others)...);
36}
37
43template <typename Arg>
44inline typename std::enable_if<!std::is_pointer<Arg>::value, bool>::type threadSafe(const Arg &workspace) {
45 return workspace.threadSafe();
46}
47
55template <typename Arg, typename... Args>
56inline typename std::enable_if<!std::is_pointer<Arg>::value, bool>::type threadSafe(const Arg &workspace,
57 Args &&...others) {
58 return workspace.threadSafe() && threadSafe(std::forward<Args>(others)...);
59}
60
67template <typename T, typename BinaryOp> void AtomicOp(std::atomic<T> &f, T d, BinaryOp op) {
68 T old = f.load();
69 T desired;
70 do {
71 desired = op(old, d);
72 } while (!f.compare_exchange_weak(old, desired));
73}
74
75} // namespace Kernel
76} // namespace Mantid
77
78// The syntax used to define a pragma within a macro is different on windows and
79// GCC
80#ifdef _MSC_VER
81#define PRAGMA __pragma
82#define PARALLEL_SET_CONFIG_THREADS
83#else //_MSC_VER
84#define PRAGMA(x) _Pragma(#x)
85#define PARALLEL_SET_CONFIG_THREADS \
86 setMaxCoresToConfig(); \
87 PARALLEL_SET_DYNAMIC(false);
88#endif //_MSC_VER
89
94#define PARALLEL_START_INTERRUPT_REGION \
95 if (!m_parallelException && !m_cancel) { \
96 try {
97
102#define PARALLEL_END_INTERRUPT_REGION \
103 } /* End of try block in PARALLEL_START_INTERRUPT_REGION */ \
104 catch (std::exception & ex) { \
105 if (!m_parallelException) { \
106 m_parallelException = true; \
107 g_log.error() << this->name() << ": " << ex.what() << "\n"; \
108 } \
109 } \
110 catch (...) { \
111 m_parallelException = true; \
112 } \
113 } // End of if block in PARALLEL_START_INTERRUPT_REGION
114
117#define PARALLEL_CHECK_INTERRUPT_REGION \
118 if (m_parallelException) { \
119 g_log.debug("Exception thrown in parallel region"); \
120 throw std::runtime_error(this->name() + ": error (see log)"); \
121 } \
122 interruption_point();
123
124// _OPENMP is automatically defined if openMP support is enabled in the
125// compiler.
126#ifdef _OPENMP
127
129#include <omp.h>
130
136#define PARALLEL_FOR_IF(condition) \
137 PARALLEL_SET_CONFIG_THREADS \
138 PRAGMA(omp parallel for if (condition) )
139
144#define PARALLEL_FOR_NO_WSP_CHECK() \
145 PARALLEL_SET_CONFIG_THREADS \
146 PRAGMA(omp parallel for)
147
153#define PARALLEL_FOR_NOWS_CHECK_FIRSTPRIVATE(variable) \
154 PARALLEL_SET_CONFIG_THREADS \
155 PRAGMA(omp parallel for firstprivate(variable) )
156
157#define PARALLEL_FOR_NO_WSP_CHECK_FIRSTPRIVATE2(variable1, variable2) \
158 PARALLEL_SET_CONFIG_THREADS \
159 PRAGMA(omp parallel for firstprivate(variable1, variable2) )
160
164#define IF_PARALLEL if (omp_get_num_threads() > 1)
165
169#define IF_NOT_PARALLEL if (omp_get_num_threads() == 1)
170
174#define PARALLEL_CRITICAL(name) PRAGMA(omp critical(name))
175
178#define PARALLEL_ATOMIC PRAGMA(omp atomic)
179
180#define PARALLEL_SET_NUM_THREADS(MaxCores) omp_set_num_threads(MaxCores);
181
188#define PARALLEL_SET_DYNAMIC(val) omp_set_dynamic(val)
189
190#define PARALLEL_NUMBER_OF_THREADS omp_get_num_threads()
191
192#define PARALLEL_GET_MAX_THREADS omp_get_max_threads()
193
194#define PARALLEL_THREAD_NUMBER omp_get_thread_num()
195
196#define PARALLEL PRAGMA(omp parallel)
197
198#define PARALLEL_SECTIONS PRAGMA(omp sections nowait)
199
200#define PARALLEL_SECTION PRAGMA(omp section)
201
202inline void setMaxCoresToConfig() {
203 const auto maxCores = Mantid::Kernel::ConfigService::Instance().getValue<int>("MultiThreaded.MaxCores");
204 if (maxCores.get_value_or(0) > 0) {
205 PARALLEL_SET_NUM_THREADS(maxCores.get());
206 }
207}
208
213#define PRAGMA_OMP(expression) PRAGMA(omp expression)
214
215#else //_OPENMP
216
218#define PARALLEL_FOR_IF(condition)
219#define PARALLEL_FOR_NO_WSP_CHECK()
220#define PARALLEL_FOR_NOWS_CHECK_FIRSTPRIVATE(variable)
221#define PARALLEL_FOR_NO_WSP_CHECK_FIRSTPRIVATE2(variable1, variable2)
222#define IF_PARALLEL if (false)
223#define IF_NOT_PARALLEL
224#define PARALLEL_CRITICAL(name)
225#define PARALLEL_ATOMIC
226#define PARALLEL_THREAD_NUMBER 0
227#define PARALLEL_SET_NUM_THREADS(MaxCores)
228#define PARALLEL_SET_DYNAMIC(val)
229#define PARALLEL_NUMBER_OF_THREADS 1
230#define PARALLEL_GET_MAX_THREADS 1
231#define PARALLEL
232#define PARALLEL_SECTIONS
233#define PARALLEL_SECTION
234#define PRAGMA_OMP(expression)
235#endif //_OPENMP
IPeaksWorkspace_sptr workspace
Definition: IndexPeaks.cpp:114
#define PARALLEL_SET_NUM_THREADS(MaxCores)
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
std::enable_if< std::is_pointer< Arg >::value, bool >::type threadSafe(Arg workspace)
Thread-safety check Checks the workspace to ensure it is suitable for multithreaded access.
Definition: MultiThreaded.h:22
void AtomicOp(std::atomic< T > &f, T d, BinaryOp op)
Uses std::compare_exchange_weak to update the atomic value f = op(f, d) Used to improve parallel scal...
Definition: MultiThreaded.h:67
Helper class which provides the Collimation Length for SANS instruments.