धागे के बीच झूठी साझाकरण तब होती है जब 2 या अधिक धागे एक ही कैश लाइन का उपयोग करते हैं।
उदा। :
struct Work {
Work(int& d) : data(d) {}
void operator()() {
++data;
}
int& data;
};
int main() {
int false_sharing[10] = { 0 };
boost::thread_group threads;
for (int i = 0; i < 10; ++i)
threads.create_thread(Work(false_sharing[i]));
threads.join_all();
int no_false_sharing[10 * CACHELINE_SIZE_INTS] = { 0 };
for (int i = 0; i < 10; ++i)
threads.create_thread(Work(no_false_sharing[i * CACHELINE_SIZE_INTS]));
threads.join_all();
}
पहले ब्लॉक में धागे झूठी साझाकरण से ग्रस्त हैं। दूसरे ब्लॉक में धागे नहीं (CACHELINE_SIZE
के लिए धन्यवाद)।
ढेर पर डेटा हमेशा अन्य धागे से दूर 'दूर' होता है। (खिड़कियों के नीचे, कम से कम कुछ पेज)।
फ़ंक्शन ऑब्जेक्ट की आपकी परिभाषा के साथ, झूठी साझाकरण दिखाई दे सकती है, क्योंकि Work
के उदाहरण ढेर पर बनाए जाते हैं और यह ढेर स्थान थ्रेड के अंदर उपयोग किया जाता है।
इससे कई Work
उदाहरण सामने आ सकते हैं और इसलिए कैश लाइनों को साझा करना पड़ सकता है।
लेकिन ... आपका नमूना समझ में नहीं आता है, क्योंकि डेटा को कभी भी स्पर्श नहीं किया जाता है और इसलिए झूठी साझाकरण को बेकार ढंग से प्रेरित किया जाता है।
इस तरह की समस्याओं को रोकने के लिए सबसे आसान तरीका है, अपने 'साझा' डेटा को स्थानीय रूप से स्टैक पर कॉपी करना है, और फिर स्टैक प्रति पर काम करना है। जब आपका काम समाप्त हो जाता है तो उसे आउटपुट var पर वापस कॉपी करें।
उदा:
struct Work {
Work(int& d) : data(d) {}
void operator()()
{
int tmp = data;
for(int i = 0; i < lengthy_op; ++i)
++tmp;
data = tmp;
}
int& data;
};
यह साझा के साथ सभी समस्याओं से बचाता है।
कोड बेहतर काम करेगा। यदि आपके फ़ंक्शन ऑब्जेक्ट्स में 'स्थिर' डेटा है, तो सभी थ्रेड उस डेटा को साझा करेंगे। – GManNickG
सोचें कि आपको यह बताने की ज़रूरत है कि "प्रत्येक धागे की अपनी प्रतिलिपि प्राप्त होती है" और "स्थिर रूप से आवंटित" से आपका क्या मतलब है। धागे एक दूसरे की प्रतिलिपि बनाते हैं? – Elemental
@Elemental: कुछ कंपाइलर टीएलएस-थ्रेड स्थानीय भंडारण का उपयोग कर सकते हैं। इसका मतलब है कि आप स्थिर और थ्रेड-सुरक्षित रूप से आवंटित कर सकते हैं, हालांकि धीमा है। – Puppy