我很久以前在编写c ++程序时使用过OpenMP。 Suddnely,我想到了一个问题。
" OpenMP如何知道嵌套了多少循环实例?"
是否由编译器明确计算?
答案 0 :(得分:2)
OpenMP运行时会在线程局部变量中跟踪此信息。
可能是最流行的OpenMP实现之一,libgomp
,是开源的;这意味着人们不仅可以阅读其文档,还可以完全免费阅读其源代码。
omp_get_level()
的实施是here:
int
omp_get_level (void)
{
return gomp_thread ()->ts.level;
}
gomp_thread()
的实施是here。它检索指向线程局部结构的指针。
#if defined __nvptx__
extern struct gomp_thread *nvptx_thrs __attribute__((shared));
static inline struct gomp_thread *gomp_thread (void)
{
int tid;
asm ("mov.u32 %0, %%tid.y;" : "=r" (tid));
return nvptx_thrs + tid;
}
#elif defined HAVE_TLS || defined USE_EMUTLS
extern __thread struct gomp_thread gomp_tls_data;
static inline struct gomp_thread *gomp_thread (void)
{
return &gomp_tls_data;
}
#else
extern pthread_key_t gomp_tls_key;
static inline struct gomp_thread *gomp_thread (void)
{
return pthread_getspecific (gomp_tls_key);
}
#endif
数据结构ts
是struct gomp_team_state
,其中包括contains:
[...]
/* Nesting level. */
unsigned level;
/* Active nesting level. Only active parallel regions are counted. */
unsigned active_level;
[...]
每当使用#pragma omp parallel
时,编译器会将并行部分的主体提取到子函数中,并生成一组复杂的函数调用,最终导致gomp_team_start()
,contains:
#ifdef LIBGOMP_USE_PTHREADS
void
gomp_team_start (void (*fn) (void *), void *data, unsigned nthreads,
unsigned flags, struct gomp_team *team)
{
[...]
++thr->ts.level;
if (nthreads > 1)
++thr->ts.active_level;