7 #ifndef TREELITE_THREADING_UTILS_PARALLEL_FOR_H_ 8 #define TREELITE_THREADING_UTILS_PARALLEL_FOR_H_ 13 #include <type_traits> 21 namespace threading_utils {
23 inline int OmpGetThreadLimit() {
24 int limit = omp_get_thread_limit();
25 TREELITE_CHECK_GE(limit, 1) <<
"Invalid thread limit for OpenMP.";
29 inline int MaxNumThread() {
30 return std::min(std::min(omp_get_num_procs(), omp_get_max_threads()), OmpGetThreadLimit());
37 std::uint32_t nthread;
48 nthread = MaxNumThread();
49 TREELITE_CHECK_GE(nthread, 1) <<
"Invalid number of threads configured in OpenMP";
51 TREELITE_CHECK_LE(nthread, MaxNumThread())
52 <<
"nthread cannot exceed " << MaxNumThread() <<
" (configured by OpenMP).";
54 return ThreadConfig{
static_cast<std::uint32_t
>(nthread)};
73 template <
typename IndexType,
typename FuncType>
74 inline void ParallelFor(IndexType begin, IndexType end,
const ThreadConfig& thread_config,
82 using OmpInd = std::conditional_t<std::is_signed<IndexType>::value, IndexType, std::int64_t>;
84 using OmpInd = IndexType;
88 switch (sched.sched) {
89 case ParallelSchedule::kAuto: {
90 #pragma omp parallel for num_threads(thread_config.nthread) 91 for (OmpInd i = begin; i < end; ++i) {
92 exc.
Run(func, static_cast<IndexType>(i), omp_get_thread_num());
96 case ParallelSchedule::kDynamic: {
97 if (sched.chunk == 0) {
98 #pragma omp parallel for num_threads(thread_config.nthread) schedule(dynamic) 99 for (OmpInd i = begin; i < end; ++i) {
100 exc.
Run(func, static_cast<IndexType>(i), omp_get_thread_num());
103 #pragma omp parallel for num_threads(thread_config.nthread) schedule(dynamic, sched.chunk) 104 for (OmpInd i = begin; i < end; ++i) {
105 exc.
Run(func, static_cast<IndexType>(i), omp_get_thread_num());
110 case ParallelSchedule::kStatic: {
111 if (sched.chunk == 0) {
112 #pragma omp parallel for num_threads(thread_config.nthread) schedule(static) 113 for (OmpInd i = begin; i < end; ++i) {
114 exc.
Run(func, static_cast<IndexType>(i), omp_get_thread_num());
117 #pragma omp parallel for num_threads(thread_config.nthread) schedule(static, sched.chunk) 118 for (OmpInd i = begin; i < end; ++i) {
119 exc.
Run(func, static_cast<IndexType>(i), omp_get_thread_num());
124 case ParallelSchedule::kGuided: {
125 #pragma omp parallel for num_threads(thread_config.nthread) schedule(guided) 126 for (OmpInd i = begin; i < end; ++i) {
127 exc.
Run(func, static_cast<IndexType>(i), omp_get_thread_num());
138 #endif // TREELITE_THREADING_UTILS_PARALLEL_FOR_H_ Represent thread configuration, to be used with parallel loops.
logging facility for Treelite
ThreadConfig ConfigureThreadConfig(int nthread)
Create therad configuration.
Utility to propagate exceptions throws inside an OpenMP block.
void Run(Function f, Parameters... params)
Parallel OMP blocks should be placed within Run to save exception.
OMP Exception class catches, saves and rethrows exception from OMP blocks.
compatiblity wrapper for systems that don't support OpenMP
void Rethrow()
should be called from the main thread to rethrow the exception