Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
gcc“线程”是如何工作的?_C_Multithreading_Gcc_Thread Local Storage - Fatal编程技术网

gcc“线程”是如何工作的?

gcc“线程”是如何工作的?,c,multithreading,gcc,thread-local-storage,C,Multithreading,Gcc,Thread Local Storage,gcc中的线程是如何实现的?它只是pthread\u getspecific和pthread\u setspecific的包装器吗 对于我使用POSIXAPI for TLS的程序,现在看到30%的程序运行时都花在pthread\u getspecific上,我有点失望。我在每个需要资源的函数调用的入口调用它。在内联优化之后,编译器似乎没有优化出pthread\u getspecific。因此,在函数内联之后,代码基本上是一次又一次地搜索正确的TLS指针,以返回相同的指针 在这种情况下,\u t

gcc中的线程是如何实现的?它只是
pthread\u getspecific
pthread\u setspecific
的包装器吗

对于我使用POSIXAPI for TLS的程序,现在看到30%的程序运行时都花在
pthread\u getspecific
上,我有点失望。我在每个需要资源的函数调用的入口调用它。在内联优化之后,编译器似乎没有优化出
pthread\u getspecific
。因此,在函数内联之后,代码基本上是一次又一次地搜索正确的TLS指针,以返回相同的指针

在这种情况下,
\u thread
能帮我吗?我知道C11中有
thread\u local
,但是我的gcc还不支持它。(但现在我看到我的gcc确实支持
\u Thread\u local
,只是不支持宏。)


我知道我可以简单地测试一下,然后看看。但是我现在必须去别的地方,我想在我尝试一个相当大的重写之前更好地了解一个特性。

gcc的
\uuuThread
与C11的
\uThread\uLocal
具有完全相同的语义。您没有告诉我们您为哪个平台编程,因为不同平台的实现细节不同。例如,在x86 Linux上,gcc应该使用
%fs
段前缀将对线程局部变量的访问编译为内存指令,而不是调用
pthread\u getspecific

,例如,确实支持C11及其
thread\u local
(如果使用
gcc-std=C11
进行编译)。如前所述,您可以使用(而不是C11
thread\u local
)旧GCC版本支持的
\u thread
限定符。了解

pthread_getspecific
确实非常慢(它在POSIX库中,因此不是由GCC提供的,而是由或提供的),因为它涉及函数调用。使用
thread\u local
变量可能会更快

查看的源代码 以实现为例。阅读相关问题

\u thread
thread\u local
通常不会神奇地转换为调用
pthread\u getspecific
。它们通常涉及一些特定的地址模式和/或寄存器(详细信息是特定于实现的,与;在Linux上,我想因为x86-64有更多的寄存器和地址模式,所以它的TLS实现速度比在i386上更快),并得到了、和的帮助。相反,
pthread\u getspecific
的一些实现可能使用一些内部
thread\u local
变量(在POSIX线程的实现中)

例如,编译以下代码

#include <pthread.h>

const extern pthread_key_t key;

__thread int data;

int
get_data (void) {
  return data;
}

int
get_by_key (void) {
  return *(int*) (pthread_getspecific (key));
}
下面的代码是
get_by_key
,显式调用
pthread\u getspecific

get_by_key:
 .LFB4:
  .cfi_startproc
  subl  $24, %esp   #,
  .cfi_def_cfa_offset 28
  pushl key # key
  .cfi_def_cfa_offset 32
  call  pthread_getspecific #
  movl  (%eax), %eax    # MEM[(int *)_4], MEM[(int *)_4]
  addl  $28, %esp   #,
  .cfi_def_cfa_offset 4
  ret
  .cfi_endproc
因此,将TLS与
\uuuuThread
(或C11中的
thread\uLocal
)一起使用可能比使用
pthread\uGetSpecific
(避免调用开销)更快


请注意,
thread\u local
是一个(C11标准头)。

我使用的是英特尔cpu。你是说gcc使用一个特殊的寄存器,比如堆栈指针寄存器,但专用于TLS?pthread_getspecific也做同样的事情吗?@xiver77“我正在使用英特尔cpu”的信息不够。您为什么操作系统和体系结构编程?英特尔生产具有多种不同体系结构的CPU。在i386平台上,如果ABI支持此功能,则将
%fp
段寄存器设置为指向线程本地数据的非零基址。我不能告诉你gcc是否可以在你的平台上这样做,因为你没有给我足够的信息。您还可以给我gcc的版本、gcc的调用和程序集输出(使用
-S
开关)吗?很抱歉回复太晚。我的平台是Ubuntu15.10i386GCC4.9.2。我现在还将检查并查看
\uuu thread
的程序集输出。@xiver77如何调用gcc?在i386 Linux上,gcc应该编译对
\uuuuuThread
变量的访问,而不调用
pthread\uGetSpecific
。代码的另一部分调用了
pthread\u getspecific
,或者发生了一些奇怪的事情。@xiver77此程序集根本不调用
pthread\u getspecific
。我猜这些调用来自其他地方。pthread_setspecific是否比内置TLS做了更多额外的工作?
\u thread
是gcc的前C11扩展,其语义与C11的
\u thread\u local
相同,事实上它保证比
\u thread\u local
多一点
pthread_getspecific
不一定涉及函数调用,它可以作为宏来实现。@fuzzxl:它可以通过宏来实现(但我想标准要求您可以通过函数指针来使用它),但它通常不作为宏来实现macro@BasileStarynkevitch标准说它可以是宏的,奇怪的是,glibc没有实现它。TLS在i386和amd64 Linux上都是通过段寄存器实现的(i386是
%fs
,amd64是
%gs
)。速度差异可以忽略不计。
\u线程
在不同的平台上实现不同,在某些平台上(您没有告诉我们您是为哪个平台编程的),它可能使用
pthread\u getspecific
实现。请给我们更多信息!我真的很想解决您的问题,但现在我对您使用的平台/如何编译代码的了解还不够,无法回答如何使线程本地存储性能更好。
get_by_key:
 .LFB4:
  .cfi_startproc
  subl  $24, %esp   #,
  .cfi_def_cfa_offset 28
  pushl key # key
  .cfi_def_cfa_offset 32
  call  pthread_getspecific #
  movl  (%eax), %eax    # MEM[(int *)_4], MEM[(int *)_4]
  addl  $28, %esp   #,
  .cfi_def_cfa_offset 4
  ret
  .cfi_endproc