Recenti GCC, ad es. GCC 5 supportano C11 e il suo thread_local
(se si compila con ad esempio gcc -std=c11
). Come commentato FUZxxl, è possibile utilizzare (anziché C11 thread_local
) il qualificatore __thread
supportato dalle versioni GCC precedenti. Maggiori informazioni su Thread Local Storage.
pthread_getspecific
è infatti abbastanza lento (che si trova nella libreria POSIX, quindi non viene fornito da GCC ma per esempio mediante GNU glibc o musl-libc) poiché comporta una chiamata di funzione. L'utilizzo delle variabili thread_local
sarà probabilmente più veloce.
Cercare il codice sorgente di MUSL's thread/pthread_getspecific.c
file per un esempio di implementazione. Leggi this answer per una domanda correlata.
E _thread
& thread_local
sono (spesso) non magicamente tradotto per le chiamate verso pthread_getspecific
. Di solito coinvolgono alcune modalità di indirizzo e/o registro specifici (i dettagli sono specifici dell'implementazione, relativi allo ABI; su Linux, suppongo che dal momento che x86-64 abbia più registri delle modalità di indirizzo &, la sua implementazione di TLS sia più veloce che su i386), con l'aiuto di compiler, linker e runtime system. Potrebbe accadere, al contrario, che alcune implementazioni di pthread_getspecific
utilizzino alcune variabili interne thread_local
(nell'implementazione dei thread POSIX).
Come esempio, compilando il seguente codice
#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));
}
usando GCC 5.2 (su Debian/Sid) con gcc -m32 -S -O2 -fverbose-asm
pronunciato la seguente codice per get_data
utilizzando TLS:
.type get_data, @function
get_data:
.LFB3:
.cfi_startproc
movl %gs:[email protected], %eax # data,
ret
.cfi_endproc
e il seguente codice di get_by_key
con una chiamata esplicita a pthread_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
Quindi utilizzare TLS con __thread
(o thread_local
in C11) dovrebbe probabilmente essere più veloce rispetto all'utilizzo di pthread_getspecific
(evitando il sovraccarico di una chiamata).
Si noti che thread_local
è un convenience macro defined in <threads.h>
(un'intestazione standard C11).
'__thread' è implementato in modo diverso su piattaforme diverse, su alcuni (non ci hai detto per quale programma stai programmando), potrebbe essere implementato con' pthread_getspecific'. – fuz
Per favore ci dia più informazioni! Mi piacerebbe davvero risolvere il tuo problema ma al momento non ne so abbastanza su quale piattaforma usi/come compili il tuo codice per essere in grado di darti una risposta su come rendere il thread storage locale più performante. – fuz