考虑以下程序:
#include <pthread.h>
static int final_value = 0;
#ifdef TLS_VAR
static int __thread tls_var;
#else
static int tls_var;
#endif
void __attribute__ ((noinline)) modify_tls(void) {
tls_var++;
}
void *thread_function(void *unused) {
const int iteration_count = 1 << 25;
tls_var = 0;
for (int i = 0; i < iteration_count; i++) {
modify_tls();
}
final_value += tls_var;
return NULL;
}
int main() {
const int thread_count = 1 << 7;
pthread_t thread_ids[thread_count];
for (int i = 0; i < thread_count; i++) {
pthread_create(&thread_ids[i], NULL, thread_function, NULL);
}
for (int i = 0; i < thread_count; i++) {
pthread_join(thread_ids[i], NULL);
}
return 0;
}
在我的 i7 上,执行定义需要 1.308 秒,TLS_VAR
未定义执行需要 8.392 秒;我无法解释如此巨大的差异。
的组件modify_tls
看起来像这样(我只提到了不同的部分):
;; !defined(TLS_VAR)
movl tls_var(%rip), %eax
addl $1, %eax
movl %eax, tls_var(%rip)
;; defined(TLS_VAR)
movl %fs:tls_var@tpoff, %eax
addl $1, %eax
movl %eax, %fs:tls_var@tpoff
TLS 查找是可以理解的,有来自 TCB 的负载。但是为什么tls_var
第一种情况下的负载相对于%rip
?为什么它不能是由加载器重定位的直接内存地址?这种%rip
相对负载是造成缓慢的原因吗?如果是这样,为什么?
编译标志:gcc -O3 -std=c99 -Wall -Werror -lpthread