2015-08-27 11 views
15

जीसीसी में __thread कैसे लागू किया गया है? क्या यह pthread_getspecific और pthread_setspecific पर बस एक रैपर है?जीसीसी `__thread` कैसे काम करता है?

टीएलएस के लिए पॉज़िक्स एपीआई का उपयोग करने वाले मेरे प्रोग्राम के साथ, अब मैं निराश हूं कि मेरे प्रोग्राम रनटाइम का 30% pthread_getspecific पर खर्च किया गया है। मैंने इसे प्रत्येक फंक्शन कॉल के प्रवेश पर बुलाया जिसे संसाधन की आवश्यकता है। अनुकूलन को इनलाइन करने के बाद संकलक pthread_getspecific को अनुकूलित करने के लिए प्रतीत नहीं होता है। तो फ़ंक्शंस को रेखांकित करने के बाद कोड मूल रूप से एक ही पॉइंटर लौटने के लिए सही टीएलएस पॉइंटर की खोज कर रहा है।

__thread इस स्थिति में मेरी मदद करेंगी? मुझे पता है कि सी 11 में thread_local है, लेकिन मेरे पास जीसीसी अभी तक इसका समर्थन नहीं करता है। (लेकिन अब मुझे लगता है कि मेरा जीसीसी _Thread_local का समर्थन करता है सिर्फ मैक्रो नहीं।)

मुझे पता है कि मैं बस इसका परीक्षण कर सकता हूं और देख सकता हूं। लेकिन मुझे अब कहीं और जाना है, और मैं काफी बड़ी पुनर्लेखन करने से पहले एक सुविधा पर बेहतर जानना चाहता हूं।

+1

'__thread' विभिन्न प्लेटफार्मों पर अलग ढंग से कार्यान्वित किया जाता है, कुछ पर (आप हमें नहीं बताया है जो आप के लिए प्रोग्रामिंग कर रहे हैं एक), यह' pthread_getspecific' साथ लागू किया जा सकता है। – fuz

+0

कृपया हमें और जानकारी दें! मैं वास्तव में अपनी समस्या को हल करने के लिए लेकिन अभी मैं तुम्हें क्या मंच का उपयोग/कैसे आप अपने कोड कैसे धागा स्थानीय भंडारण बेहतर प्रदर्शन करने के लिए के रूप में आप एक जवाब देने के लिए सक्षम होने के लिए संकलन के बारे में पर्याप्त जानकारी नहीं है चाहते हैं। – fuz

उत्तर

8

हालिया GCC, उदा। GCC 5 सी 11 और उसके thread_local का समर्थन करते हैं (उदाहरण के साथ gcc -std=c11 के साथ संकलित)। FUZxxl टिप्पणी के रूप में, आप उपयोग कर सकते हैं (C11 thread_local के बजाय) __thread पुराने जीसीसी संस्करणों द्वारा समर्थित क्वालीफायर। Thread Local Storage के बारे में पढ़ें।

pthread_getspecific वास्तव में बहुत धीमी गति से (यह POSIX पुस्तकालय में है, इसलिए जीसीसी द्वारा लेकिन GNU glibc या musl-libc द्वारा उदा प्रदान नहीं की है) के बाद से यह एक समारोह कॉल किया जाता है। thread_local चर का उपयोग करना शायद तेज़ होगा।

कार्यान्वयन के उदाहरण के लिए MUSL's thread/pthread_getspecific.c file के स्रोत कोड में देखें। संबंधित प्रश्न पर this answer पढ़ें।

और _thread & thread_local (अक्सर) pthread_getspecific पर जादुई रूप से अनुवाद करने के लिए अनुवादित नहीं हैं। वे आमतौर पर कुछ विशिष्ट पता मोड और/या रजिस्टर (विवरण ABI से संबंधित कार्यान्वयन विशिष्ट हैं; लिनक्स पर, मुझे लगता है कि चूंकि x86-64 में अधिक रजिस्ट्रार & पता मोड हैं, इसलिए टीएलएस का कार्यान्वयन i386 से तेज है), compiler, linker और runtime system से सहायता के साथ। इसके विपरीत यह हो सकता है कि pthread_getspecific के कुछ कार्यान्वयन कुछ आंतरिक thread_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)); 
} 

जीसीसी 5 का उपयोग कर संकलन।

.type get_data, @function 
get_data: 
.LFB3: 
    .cfi_startproc 
    movl %gs:[email protected], %eax # data, 
    ret 
.cfi_endproc 

और एक स्पष्ट कॉल के साथ get_by_key के निम्नलिखित कोड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 

इसलिए TLS का उपयोग 2 gcc -m32 -S -O2 -fverbose-asm साथ (Debian/सिड पर) get_data TLS का उपयोग करने के लिए निम्न कोड देता है __thread (या thread_local सी 11) के साथ शायद pthread_getspecific का उपयोग कर (एक फोन की भूमि के ऊपर से परहेज) की तुलना में तेजी से किया जाना चाहिए।

ध्यान दें कि thread_local एक convenience macro defined in <threads.h> (एक C11 मानक शीर्षलेख) है।

+0

क्या pthread_setspecific अंतर्निहित टीएलएस की तुलना में अधिक अतिरिक्त काम करता है? – xiver77

+0

'__thread' जीसीसी का प्री-सी 11 एक्सटेंशन है जो सी 11 के' _Thread_local' के समान अर्थपूर्ण है, वास्तव में यह '_Thread_local' से थोड़ा अधिक गारंटी देता है। 'pthread_getspecific' में फ़ंक्शन कॉल शामिल नहीं है, इसे मैक्रो के रूप में कार्यान्वित किया जा सकता है। – fuz

+0

@FUZxxl: इसे एक मैक्रो द्वारा कार्यान्वित किया जा सकता है (लेकिन मुझे लगता है कि मानक की आवश्यकता है कि आप इसे फ़ंक्शन पॉइंटर के माध्यम से उपयोग कर सकें), लेकिन आमतौर पर इसे मैक्रो –

3

जीसीसी का __thread सी 11 के _Thread_local के समान वही अर्थपूर्ण है। आप हमें नहीं बताते कि आप किस प्लेटफॉर्म के लिए प्रोग्रामिंग कर रहे हैं क्योंकि कार्यान्वयन विवरण प्लेटफ़ॉर्म के बीच भिन्न होते हैं। उदाहरण के लिए, x86 लिनक्स पर, जीसीसी को pthread_getspecific का आह्वान करने के बजाय %fs सेगमेंट उपसर्ग के साथ स्मृति निर्देशों के रूप में थ्रेड स्थानीय चरों तक पहुंच संकलित करना चाहिए।

+0

मैं एक इंटेल सीपीयू का उपयोग कर रहा हूँ। तो आपका मतलब है कि जीसीसी एक विशेष रजिस्टर का उपयोग करता है जैसे स्टैक पॉइंटर रजिस्टर लेकिन टीएलएस को समर्पित? क्या pthread_getspecific एक ही काम करता है? – xiver77

+0

@ xiver77 "मैं एक इंटेल सीपीयू का उपयोग कर रहा हूं" पर्याप्त जानकारी नहीं है। आप किस ऑपरेटिंग सिस्टम और आर्किटेक्चर के लिए प्रोग्रामिंग कर रहे हैं? इंटेल कई अलग-अलग आर्किटेक्चर के साथ सीपीयू बनाता है। I386 प्लेटफ़ॉर्म पर एबीआई इसका समर्थन करता था, '% fp' सेगमेंट रजिस्टर गैर-शून्य आधार पते पर सेट होता है जो थ्रेड के थ्रेड-स्थानीय डेटा को इंगित करता है। मैं आपको नहीं बता सकता कि क्या जीसीसी आपके मंच पर ऐसा कर सकता है क्योंकि आप मुझे पर्याप्त जानकारी नहीं देते हैं। क्या आप मुझे जीसीसी का संस्करण भी दे सकते हैं, जीसीसी और असेंबली आउटपुट का आविष्कार ('-S' स्विच का उपयोग करें)? – fuz

+0

देर से उत्तर के लिए खेद है। मेरा मंच उबंटू 15.10 i386 जीसीसी 4.9.2 है। मैं अभी भी '__thread' के लिए असेंबली आउटपुट की जांच और देखूंगा। – xiver77

संबंधित मुद्दे