/
MultiThreaded.h
196 lines (160 loc) · 6.88 KB
/
MultiThreaded.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
#ifndef MANTID_KERNEL_MULTITHREADED_H_
#define MANTID_KERNEL_MULTITHREADED_H_
#include <Poco/Mutex.h>
namespace Mantid
{
namespace Kernel
{
//==============================================================================================
// Typedefs for ThreadPool
/// General mutex (typedef'd to Poco::FastMutex). Not recursive in general; don't assume it is!
typedef Poco::FastMutex Mutex;
typedef Poco::Mutex RecursiveMutex;
} //namespace
} //namespace
// The syntax used to define a pragma within a macro is different on windows and GCC
#ifdef _MSC_VER
#define PRAGMA __pragma
#else //_MSC_VER
#define PRAGMA(x) _Pragma(#x)
#endif //_MSC_VER
/** Begins a block to skip processing is the algorithm has been interupted
* Note the end of the block if not defined that must be added by including
* PARALLEL_END_INTERUPT_REGION at the end of the loop
*/
#define PARALLEL_START_INTERUPT_REGION \
if (!m_parallelException && !m_cancel) { \
try {
/** Ends a block to skip processing is the algorithm has been interupted
* Note the start of the block if not defined that must be added by including
* PARALLEL_START_INTERUPT_REGION at the start of the loop
*/
#define PARALLEL_END_INTERUPT_REGION \
} /* End of try block in PARALLEL_START_INTERUPT_REGION */ \
catch(std::exception &ex) { \
if (!m_parallelException) \
{ \
m_parallelException = true; \
g_log.error() << this->name() << ": " << ex.what() << "\n"; \
} \
} \
catch(...) { m_parallelException = true; } \
} // End of if block in PARALLEL_START_INTERUPT_REGION
/** Adds a check after a Parallel region to see if it was interupted
*/
#define PARALLEL_CHECK_INTERUPT_REGION \
if (m_parallelException) \
{ \
g_log.debug("Exception thrown in parallel region"); \
throw std::runtime_error(this->name()+": error (see log)"); \
} \
interruption_point();
// _OPENMP is automatically defined if openMP support is enabled in the compiler.
#ifdef _OPENMP
#include <omp.h>
/** Includes code to add OpenMP commands to run the next for loop in parallel.
* This includes an arbirary check: condition.
* "condition" must evaluate to TRUE in order for the
* code to be executed in parallel
*/
#define PARALLEL_FOR_IF(condition) \
PRAGMA(omp parallel for if (condition) )
/** Includes code to add OpenMP commands to run the next for loop in parallel.
* This includes no checks to see if workspaces are suitable
* and therefore should not be used in any loops that access workspaces.
*/
#define PARALLEL_FOR_NO_WSP_CHECK() \
PRAGMA(omp parallel for)
/** Includes code to add OpenMP commands to run the next for loop in parallel.
* and declare the varialbes to be firstprivate.
* This includes no checks to see if workspaces are suitable
* and therefore should not be used in any loops that access workspace.
*/
#define PARALLEL_FOR_NOWS_CHECK_FIRSTPRIVATE(variable) \
PRAGMA(omp parallel for firstprivate(variable) )
#define PARALLEL_FOR_NO_WSP_CHECK_FIRSTPRIVATE2(variable1, variable2) \
PRAGMA(omp parallel for firstprivate(variable1, variable2) )
/** Includes code to add OpenMP commands to run the next for loop in parallel.
* The workspace is checked to ensure it is suitable for multithreaded access
* NULL workspaces are assumed suitable
*/
#define PARALLEL_FOR1(workspace1) \
PRAGMA(omp parallel for if ( !workspace1 || workspace1->threadSafe() ) )
/** Includes code to add OpenMP commands to run the next for loop in parallel.
* Both workspaces are checked to ensure they suitable for multithreaded access
* or equal to NULL which is also safe
*/
#define PARALLEL_FOR2(workspace1, workspace2) \
PRAGMA(omp parallel for if ( ( !workspace1 || workspace1->threadSafe() ) && \
( !workspace2 || workspace2->threadSafe() ) ))
/** Includes code to add OpenMP commands to run the next for loop in parallel.
* All three workspaces are checked to ensure they are suitable for multithreaded access
* but NULL workspaces are assumed to be safe
*/
#define PARALLEL_FOR3(workspace1, workspace2, workspace3) \
PRAGMA(omp parallel for if ( (!workspace1 || workspace1->threadSafe()) && \
( !workspace2 || workspace2->threadSafe() ) && \
( !workspace3 || workspace3->threadSafe() ) ))
/** Ensures that the next execution line or block is only executed if
* there are multple threads execting in this region
*/
#define IF_PARALLEL \
if (omp_get_num_threads() > 1)
/** Ensures that the next execution line or block is only executed if
* there is only one thread in operation
*/
#define IF_NOT_PARALLEL \
if (omp_get_num_threads() == 1)
/** Specifies that the next code line or block will only allow one thread through at a time
*/
#define PARALLEL_CRITICAL(name) \
PRAGMA(omp critical(name))
/** Allows only one thread at a time to write to a specific memory location
*/
#define PARALLEL_ATOMIC \
PRAGMA(omp atomic)
#define PARALLEL_SET_NUM_THREADS(MaxCores) omp_set_num_threads(MaxCores);
/** A value that indicates if the number of threads available in subsequent parallel region
* can be adjusted by the runtime. If nonzero, the runtime can adjust the number of threads,
* if zero, the runtime will not dynamically adjust the number of threads.
*/
#define PARALLEL_SET_DYNAMIC(val) omp_set_dynamic(val)
#define PARALLEL_NUMBER_OF_THREADS omp_get_num_threads()
#define PARALLEL_GET_MAX_THREADS omp_get_max_threads()
#define PARALLEL_THREAD_NUMBER omp_get_thread_num()
#define PARALLEL \
PRAGMA(omp parallel)
#define PARALLEL_SECTIONS \
PRAGMA(omp sections nowait)
#define PARALLEL_SECTION \
PRAGMA(omp section)
/** General purpose define for OpenMP, becomes the equivalent of
* #pragma omp EXPRESSION
* (if your compiler supports OpenMP)
*/
#define PRAGMA_OMP(expression) \
PRAGMA(omp expression )
#else //_OPENMP
///Empty definitions - to enable set your complier to enable openMP
#define PARALLEL_FOR_IF(condition)
#define PARALLEL_FOR_NO_WSP_CHECK()
#define PARALLEL_FOR_NOWS_CHECK_FIRSTPRIVATE(variable)
#define PARALLEL_FOR_NO_WSP_CHECK_FIRSTPRIVATE2(variable1, variable2)
#define PARALLEL_FOR1(workspace1)
#define PARALLEL_FOR2(workspace1, workspace2)
#define PARALLEL_FOR3(workspace1, workspace2, workspace3)
#define IF_PARALLEL if (false)
#define IF_NOT_PARALLEL
#define PARALLEL_CRITICAL(name)
#define PARALLEL_ATOMIC
#define PARALLEL_THREAD_NUMBER 0
#define PARALLEL_SET_NUM_THREADS(MaxCores)
#define PARALLEL_SET_DYNAMIC(val)
#define PARALLEL_NUMBER_OF_THREADS 1
#define PARALLEL_GET_MAX_THREADS 1
#define PARALLEL
#define PARALLEL_SECTIONS
#define PARALLEL_SECTION
#define PRAGMA_OMP(expression)
#endif //_OPENMP
#endif //MANTID_KERNEL_MULTITHREADED_H_