54 lines
2.2 KiB
C++
54 lines
2.2 KiB
C++
#pragma once
|
||
|
||
#include <vector>
|
||
#include <omp.h>
|
||
|
||
|
||
namespace omp_config{
|
||
|
||
// Configure OpenMP behavior at runtime.
|
||
inline void omp_configure(int max_active_levels,
|
||
bool dynamic_threads,
|
||
const std::vector<int>& threads_per_level = {},
|
||
bool bind_close = true)
|
||
{
|
||
// 1) Allow nested parallel regions (levels of teams)
|
||
// Example: outer #pragma omp parallel ... { inner #pragma omp parallel ... }
|
||
omp_set_max_active_levels(max_active_levels); // 1 = only top-level; 2+ enables nesting
|
||
|
||
// 2) Let the runtime shrink/grow thread counts if it thinks it should
|
||
// (helps avoid oversubscription when you accidentally ask for too many threads)
|
||
omp_set_dynamic(dynamic_threads ? 1 : 0);
|
||
|
||
// 3) Thread binding (keep threads near their cores) is controlled via env vars,
|
||
// so here we just *recommend* a good default (see below). You *can* setenv()
|
||
// in code, but it’s cleaner to do it outside the program.
|
||
(void)bind_close; // documented below in env var section
|
||
|
||
// 4) Top-level default thread count (inner levels are usually set per region)
|
||
if (!threads_per_level.empty()) {
|
||
omp_set_num_threads(threads_per_level[0]); // e.g. 16 for the outermost team
|
||
// Inner levels:
|
||
// - Use num_threads(threads_per_level[L]) on the inner #pragma omp parallel
|
||
// - or set OMP_NUM_THREADS="outer,inner,inner2" as an environment variable
|
||
}
|
||
}
|
||
|
||
// ---------- Helper: may we create another team? ----------
|
||
inline bool omp_parallel_allowed() {
|
||
#ifdef _OPENMP
|
||
// If we’re not in parallel, we can spawn.
|
||
if (!omp_in_parallel()) return true;
|
||
|
||
// Already inside parallel: allow only if nesting is enabled and not at limit.
|
||
int level = omp_get_active_level(); // 0 outside parallel, 1 inside, ...
|
||
int maxlv = omp_get_max_active_levels(); // user/runtime cap
|
||
return static_cast<bool>(level < maxlv);
|
||
#else
|
||
return false; // no OpenMP → no extra teams
|
||
#endif
|
||
}
|
||
|
||
|
||
} // namespace omp_config
|