|
6 | 6 | #include "copasi/OpenMP/COpenMPConfig.h" |
7 | 7 | #include "copasi/OpenMP/CContext.h" |
8 | 8 |
|
9 | | -#ifdef USE_OMP |
10 | | -# include <omp.h> |
11 | | -#else |
12 | | -# define omp_sched_static 1u |
13 | | -# define omp_sched_dynamic 2u |
14 | | -# define omp_sched_guided 3u |
15 | | -# define omp_sched_auto 4u |
16 | | -typedef unsigned int omp_sched_t; |
17 | | -#endif // USE_OMP |
| 9 | +// static |
| 10 | +const COpenMPConfig::ScheduleStrategyName COpenMPConfig::ScheduleStrategyNames({"static", |
| 11 | + "dynamic", |
| 12 | + "guided", |
| 13 | + "automatic"}); |
| 14 | + |
| 15 | +// static |
| 16 | +const CEnumAnnotation< omp_sched_t, COpenMPConfig::ScheduleStrategy > COpenMPConfig::ScheduleStrategyOpenMP({omp_sched_static, |
| 17 | + omp_sched_dynamic, |
| 18 | + omp_sched_guided, |
| 19 | + omp_sched_auto}); |
18 | 20 |
|
19 | 21 | // static |
20 | | -const COpenMPConfig::ScheduleStrategyName COpenMPConfig::ScheduleStrategyNames({ |
21 | | - "static", |
22 | | - "dynamic", |
23 | | - "guided", |
24 | | - "automatic" |
25 | | -}); |
| 22 | +const COpenMPConfig::MonotonicName COpenMPConfig::MonotonicNames({"nonmonotonic", |
| 23 | + "monotonic"}); |
26 | 24 |
|
27 | 25 | // static |
28 | | -const CEnumAnnotation< omp_sched_t, COpenMPConfig::ScheduleStrategy > ScheduleStrategyOpenMP({ |
29 | | - omp_sched_static, |
30 | | - omp_sched_dynamic, |
31 | | - omp_sched_guided, |
32 | | - omp_sched_auto |
33 | | -}); |
| 26 | +const CEnumAnnotation< omp_sched_t, COpenMPConfig::Monotonic > COpenMPConfig::MonotonicOpenMP({(omp_sched_t) 0x0, // nonmonotonic |
| 27 | + omp_sched_monotonic}); |
34 | 28 |
|
35 | 29 | // static |
36 | 30 | const int COpenMPConfig::MaxNumThreads = omp_get_max_threads(); |
37 | 31 |
|
| 32 | +struct _ScheduleStrategyOpenMP |
| 33 | +{ |
| 34 | + COpenMPConfig::ScheduleStrategy scheduleStrategy = COpenMPConfig::ScheduleStrategy::Static; |
| 35 | + COpenMPConfig::Monotonic monotonicity = COpenMPConfig::Monotonic::nonmonotonic; |
| 36 | + C_UINT32 chunkSize = 0; |
| 37 | +}; |
| 38 | + |
| 39 | +_ScheduleStrategyOpenMP getSchedule() |
| 40 | +{ |
| 41 | + std::string OMP_SCHEDULE = COptions::getEnvironmentVariable("OMP_SCHEDULE"); |
| 42 | + std::string Monotonic = ""; |
| 43 | + |
| 44 | + std::string::size_type Pos = OMP_SCHEDULE.find(":"); |
| 45 | + |
| 46 | + if (Pos != std::string::npos) |
| 47 | + { |
| 48 | + Monotonic = OMP_SCHEDULE.substr(0, Pos); |
| 49 | + OMP_SCHEDULE = OMP_SCHEDULE.substr(Pos + 1); |
| 50 | + |
| 51 | +#ifndef OMP_HAVE_MONOTONIC |
| 52 | + Monotonic = "nonmonotonic"; |
| 53 | +#endif // OMP_HAVE_MONOTONIC |
| 54 | + } |
| 55 | + |
| 56 | + std::string ChunkSize; |
| 57 | + Pos = OMP_SCHEDULE.find(","); |
| 58 | + |
| 59 | + if (Pos != std::string::npos) |
| 60 | + { |
| 61 | + ChunkSize = OMP_SCHEDULE.substr(Pos + 1); |
| 62 | + OMP_SCHEDULE = OMP_SCHEDULE.substr(0, Pos); |
| 63 | + } |
| 64 | + |
| 65 | + _ScheduleStrategyOpenMP ScheduleStrategyOpenMP; |
| 66 | + ScheduleStrategyOpenMP.scheduleStrategy = COpenMPConfig::ScheduleStrategyNames.toEnum(OMP_SCHEDULE); |
| 67 | + ScheduleStrategyOpenMP.monotonicity = COpenMPConfig::MonotonicNames.toEnum(Monotonic); |
| 68 | + ScheduleStrategyOpenMP.chunkSize = (C_UINT32) ChunkSize.empty() ? -1 : std::stoi(ChunkSize); |
| 69 | + |
| 70 | + return ScheduleStrategyOpenMP; |
| 71 | +} |
| 72 | + |
38 | 73 | COpenMPConfig::COpenMPConfig(const std::string & name, |
39 | 74 | const CDataContainer * pParent) |
40 | 75 | : CCopasiParameterGroup(name, pParent) |
@@ -82,11 +117,26 @@ COpenMPConfig & COpenMPConfig::operator=(const COpenMPConfig & rhs) |
82 | 117 |
|
83 | 118 | void COpenMPConfig::apply() const |
84 | 119 | { |
| 120 | + std::string OMP_NUM_THREADS = COptions::getEnvironmentVariable("OMP_NUM_THREADS"); |
| 121 | + C_UINT32 MaxNumThreads = OMP_NUM_THREADS.empty() ? *mpMaxNumThreads : std::stoi(OMP_NUM_THREADS); |
| 122 | + |
| 123 | + _ScheduleStrategyOpenMP Schedule = getSchedule(); |
| 124 | + std::string ScheduleStrategy = Schedule.scheduleStrategy == ScheduleStrategy::__SIZE ? *mpScheduleStrategy : ScheduleStrategyNames[Schedule.scheduleStrategy]; |
| 125 | + std::string Monotonic = Schedule.monotonicity == Monotonic::__SIZE ? *mpMonotonic : MonotonicNames[Schedule.monotonicity]; |
| 126 | + C_UINT32 ChunkSize = Schedule.chunkSize == (C_UINT32) -1 ? *mpChunkSize : Schedule.chunkSize; |
| 127 | + |
| 128 | + bool IsEnabled = *mpIsEnabled || !OMP_NUM_THREADS.empty() || Schedule.scheduleStrategy != ScheduleStrategy::__SIZE; |
| 129 | + |
85 | 130 | #ifdef USE_OMP |
86 | | - if (*mpIsEnabled) |
| 131 | + if (IsEnabled) |
87 | 132 | { |
88 | | - omp_set_num_threads(*mpMaxNumThreads); |
89 | | - omp_set_schedule(ScheduleStrategyOpenMP[ScheduleStrategyNames.toEnum(*mpScheduleStrategy)], 0); |
| 133 | + omp_set_num_threads(MaxNumThreads); |
| 134 | + omp_sched_t OpenMPStrategy = |
| 135 | + ScheduleStrategyOpenMP[ScheduleStrategyNames.toEnum(ScheduleStrategy, ScheduleStrategy::Static)]; |
| 136 | + omp_sched_t OpenMPMonotonicity = |
| 137 | + MonotonicOpenMP[MonotonicNames.toEnum(Monotonic, Monotonic::nonmonotonic)]; |
| 138 | + |
| 139 | + omp_set_schedule(omp_sched_t(OpenMPStrategy | OpenMPMonotonicity), ChunkSize); |
90 | 140 | } |
91 | 141 | else |
92 | 142 | { |
@@ -146,31 +196,48 @@ bool COpenMPConfig::setScheduleStrategy(const std::string & scheduleStrategy) |
146 | 196 |
|
147 | 197 | void COpenMPConfig::initializeParameter() |
148 | 198 | { |
149 | | - mpIsEnabled = assertParameter("Enabled", CCopasiParameter::Type::BOOL, false); |
150 | | - mpMaxNumThreads = assertParameter("Max Number Threads", CCopasiParameter::Type::UINT, (C_UINT32) ceil(MaxNumThreads / 2.0)); |
151 | | - mpScheduleStrategy = assertParameter("Schedule Strategy", CCopasiParameter::Type::STRING, std::string("static")); |
| 199 | + std::string OMP_NUM_THREADS = COptions::getEnvironmentVariable("OMP_NUM_THREADS"); |
| 200 | + C_UINT32 MaxNumThreads = OMP_NUM_THREADS.empty() ? ceil(MaxNumThreads / 2.0) : std::stoi(OMP_NUM_THREADS); |
| 201 | + |
| 202 | + _ScheduleStrategyOpenMP Schedule = getSchedule(); |
| 203 | + |
| 204 | + bool IsEnabled = false || !OMP_NUM_THREADS.empty() || Schedule.scheduleStrategy != ScheduleStrategy::__SIZE; |
| 205 | + |
| 206 | + mpIsEnabled = assertParameter("Enabled", CCopasiParameter::Type::BOOL, IsEnabled); |
| 207 | + mpMaxNumThreads = assertParameter("Max Number Threads", CCopasiParameter::Type::UINT, MaxNumThreads); |
| 208 | + mpScheduleStrategy = assertParameter("Schedule Strategy", CCopasiParameter::Type::STRING, ScheduleStrategyNames[Schedule.scheduleStrategy != ScheduleStrategy::__SIZE ? Schedule.scheduleStrategy : ScheduleStrategy::Static]); |
| 209 | + mpMonotonic = assertParameter("Monotonicity", CCopasiParameter::Type::STRING, MonotonicNames[Schedule.monotonicity != Monotonic::__SIZE ? Schedule.monotonicity : Monotonic::nonmonotonic]); |
| 210 | + mpChunkSize = assertParameter("Chunk Size", CCopasiParameter::Type::UINT, Schedule.chunkSize == (C_UINT32) -1 ? 0 : Schedule.chunkSize); |
152 | 211 |
|
153 | 212 | CCopasiParameter * pMaxNumThreadsParameter = getParameter("Max Number Threads"); |
154 | | - pMaxNumThreadsParameter->setValidValues(std::vector<std::pair<C_UINT32, C_UINT32>>({{1, MaxNumThreads}})); |
| 213 | + pMaxNumThreadsParameter->setValidValues(std::vector< std::pair< C_UINT32, C_UINT32 > >({{1, MaxNumThreads}})); |
155 | 214 |
|
156 | 215 | CCopasiParameter * pScheduleStrategyParameter = getParameter("Schedule Strategy"); |
157 | 216 | pScheduleStrategyParameter->setValidValues(ScheduleStrategyNames); |
| 217 | + |
| 218 | + CCopasiParameter * pMonotonicParameter = getParameter("Monotonicity"); |
| 219 | + pMonotonicParameter->setValidValues(MonotonicNames); |
158 | 220 | } |
159 | 221 |
|
160 | 222 | std::string COpenMPConfig::Info() |
161 | 223 | { |
162 | 224 | std::ostringstream Info; |
163 | 225 |
|
164 | 226 | #ifdef USE_OMP |
165 | | - Info << " (OpenMP threads: " << omp_get_max_threads() << " schedule: "; |
| 227 | + Info << "OpenMP " << COPASI_OMP_VERSION << " (threads: " << omp_get_max_threads() << ", schedule: "; |
166 | 228 | omp_sched_t Schedule; |
167 | 229 | int Chunk; |
168 | 230 | omp_get_schedule(&Schedule, &Chunk); |
169 | 231 |
|
170 | 232 | // Schedule may have the monotonic modifier, we masked it. |
171 | | - Schedule = (omp_sched_t)(Schedule & ~omp_sched_monotonic); |
| 233 | + if (Schedule & omp_sched_monotonic) |
| 234 | + { |
| 235 | + Schedule = (omp_sched_t) (Schedule & ~omp_sched_monotonic); |
| 236 | + Info << "monotonic:"; |
| 237 | + } |
| 238 | + |
172 | 239 | Info << ScheduleStrategyNames[ScheduleStrategyOpenMP.toEnum(Schedule)]; |
173 | | - Info << "," << Chunk << ")"; |
| 240 | + Info << ", chunk size: " << Chunk << ")"; |
174 | 241 | #endif // USE_OMP |
175 | 242 |
|
176 | 243 | return Info.str(); |
|
0 commit comments