gcc中的__thread
是如何实现的?它仅仅是pthread_getspecific
和pthread_setspecific
的 Package 器吗?
我的程序使用posix API进行TLS,现在看到30%的程序运行时间花在pthread_getspecific
上,我有点失望。我在每个需要资源的函数调用的入口处调用它。编译器在内联优化后似乎没有优化出pthread_getspecific
。因此,在函数内联后,代码基本上是一次又一次地搜索正确的TLS指针,以获得相同的指针返回。__thread
在这种情况下会帮助我吗?我知道C11中有thread_local
,但我的gcc还不支持它。(但现在我看到我的gcc确实支持_Thread_local
,只是不支持宏。
我知道我可以简单地测试一下看看。但是我现在必须去别的地方,我想在尝试重写之前更好地了解一个特性。
2条答案
按热度按时间gkn4icbw1#
最近的GCC,例如GCC 5确实支持C11及其
thread_local
(如果使用例如gcc -std=c11
)。正如FUZxxl评论的那样,您可以使用旧GCC版本支持的__thread
限定符(而不是C11thread_local
)。关于Thread Local Storagepthread_getspecific
确实很慢(它在POSIX库中,所以GCC没有提供,但例如GNU glibc或musl-libc),因为它涉及函数调用。使用thread_local
变量可能会更快。查看MUSL's
thread/pthread_getspecific.c
file的源代码以获得实现示例。阅读this answer以回答相关问题。_thread
和thread_local
(通常)不会神奇地转换为对pthread_getspecific
的调用。它们通常涉及一些特定的地址模式和/或寄存器(细节是特定于实现的,与ABI有关;在Linux上,我猜由于x86-64有更多的寄存器和地址模式,它的TLS实现比i386上更快),在compiler,linker和runtime system的帮助下。相反,pthread_getspecific
的某些实现可能会使用一些内部thread_local
变量(在POSIX线程的实现中)。例如,编译以下代码
使用GCC 5.2(在Debian/Sid上)和
gcc -m32 -S -O2 -fverbose-asm
给出了以下使用TLS的get_data
代码:下面的
get_by_key
代码带有对pthread_getspecific
的 * 显式调用 *:因此,使用
__thread
(或C11中的thread_local
)的TLS可能比使用pthread_getspecific
更快(避免调用开销)。请注意,
thread_local
是一个convenience macro defined in<threads.h>
(一个C11标准头)。6l7fqoea2#
gcc的
__thread
与C11的_Thread_local
具有完全相同的语义。你没有告诉我们你是为哪个平台编程的,因为不同平台的实现细节不同。例如,在x86 Linux上,gcc应该将对线程局部变量的访问编译为带有%fs
段前缀的内存指令,而不是调用pthread_getspecific
。