我很好奇它是如何工作的,因为这个函数是在没有参数的情况下调用的,它如何找出实际调用它的线程?
答案 0 :(得分:1)
以下内容特定于GNU的OpenMP运行时库libgomp
,但其他OpenMP运行时或多或少相同。所有链接都指向GCC 4.8.2源代码的相关部分。
omp_get_thread_num()
的实际实施非常简单:
int
omp_get_thread_num (void)
{
return gomp_thread ()->ts.team_id;
}
每个线程都有一个指向struct gomp_thread
实例的线程局部指针。此外,每个线程都是线程团队的一部分,团队中的状态由struct gomp_thread_team_state
类型的ts
成员表示。后者包含一个名为unsigned int
的{{1}}成员,该成员提供其团队中线程的ID。
线程找到自己的team_id
实例的方式取决于平台是否具有TLS(线程本地存储)。在后一种情况下,TLS由POSIX线程库模拟。两种实现都是:(取自here)
使用TLS:
struct gomp_thread
extern __thread struct gomp_thread gomp_tls_data;
static inline struct gomp_thread *gomp_thread (void)
{
return &gomp_tls_data;
}
关键字使全局变量__thread
成为线程本地,这意味着每个线程都有自己的副本。
没有TLS:
gomp_tls_data
在这种情况下,extern pthread_key_t gomp_tls_key;
static inline struct gomp_thread *gomp_thread (void)
{
return pthread_getspecific (gomp_tls_key);
}
用于获取结构实例的线程局部副本(位于here)。
虽然pthread_getspecific()
也可能使用TLS来存储值,但有人可能想知道为什么提供了两种不同的实现,答案是直接访问TLS可能比调用Pthreads API函数更快。在这方面,OS X是一个特殊的情况 - Mach-O可执行格式不提供GNU兼容的TLS实现,有些人报告说Pthreads API实际上比模拟的GNU TLS更快。
答案 1 :(得分:0)
AFAIK,未指定,所以我无法给出一般答案。 GCC使用一种结构来管理线程,其中__thread
attribute。我想其他编译器中的实现将是类似的。
文档链接到PDF,它解释了TLS(线程本地存储)的工作原理:http://www.akkadia.org/drepper/tls.pdf