次のプログラムを検討してください。
#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;
}
TLS_VAR
私の i7 では、定義済みの実行に 1.308 秒、未定義の実行に 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