C ++ 11 ने एक मानकीकृत मेमोरी मॉडल पेश किया। इसका क्या मतलब है? और यह C ++ प्रोग्रामिंग को कैसे प्रभावित करने वाला है?


1894

C ++ 11 ने एक मानकीकृत मेमोरी मॉडल पेश किया, लेकिन वास्तव में इसका क्या मतलब है? और यह C ++ प्रोग्रामिंग को कैसे प्रभावित करने वाला है?

यह लेख ( गेविन क्लार्क द्वारा हर्ब सटर के उद्धरण )

मेमोरी मॉडल का अर्थ है कि C ++ कोड में अब यह संकलित करने के लिए एक मानकीकृत पुस्तकालय है कि किसने संकलक बनाया है और यह किस मंच पर चल रहा है। यह नियंत्रित करने का एक मानक तरीका है कि प्रोसेसर की मेमोरी में विभिन्न थ्रेड्स कैसे बात करते हैं।

"जब आप के बारे में बंटवारे विभिन्न कोर मानक में है कि संपूर्ण [कोड] बात कर रहे हैं, हम स्मृति मॉडल के बारे में बात कर रहे हैं। हम निम्नलिखित मान्यताओं लोगों कोड में बनाने जा रहे हैं को तोड़ने के बिना यह अनुकूलन करने के लिए जा रहे हैं," सूटर कहा।

ठीक है, मैं इसे और इसी तरह के पैराग्राफ को ऑनलाइन याद कर सकता हूं (जैसा कि जन्म से मेरा अपना मेमोरी मॉडल है: पी) और यहां तक ​​कि दूसरों द्वारा पूछे गए सवालों के जवाब के रूप में भी पोस्ट कर सकता हूं, लेकिन ईमानदारी से कहूं तो मुझे बिल्कुल समझ नहीं है इस।

C ++ प्रोग्रामर पहले भी बहु-थ्रेडेड अनुप्रयोगों को विकसित करते थे, इसलिए अगर यह POSIX थ्रेड्स, या विंडोज थ्रेड्स, या C ++ 11 थ्रेड्स है तो क्या फर्क पड़ता है? क्या लाभ हैं? मैं निम्न-स्तरीय विवरणों को समझना चाहता हूं।

मुझे यह भी महसूस होता है कि C ++ 11 मेमोरी मॉडल किसी तरह C ++ 11 मल्टी-थ्रेडिंग समर्थन से संबंधित है, क्योंकि मैं अक्सर इन दोनों को एक साथ देखता हूं। यदि यह है, तो वास्तव में कैसे? उनका संबंध क्यों होना चाहिए?

जैसा कि मुझे नहीं पता कि मल्टी-थ्रेडिंग के इंटर्न कैसे काम करते हैं, और मेमोरी मॉडल का सामान्य रूप से क्या मतलब है, कृपया मुझे इन अवधारणाओं को समझने में मदद करें। :-)


3
@ क्यूरियसग्यू: विस्तृत ...
नवाज़

4
@ क्यूरियसगू: तब एक ब्लॉग लिखें ... और साथ ही एक प्रस्ताव भी प्रस्तावित करें। अपनी बात को मान्य और औचित्यपूर्ण बनाने का कोई और तरीका नहीं है।
नवाज

2
मैंने उस साइट को क्यू पूछने और विचारों का आदान-प्रदान करने के स्थान के रूप में गलत समझा। मेरी गलती; यह अनुरूपता के लिए वह स्थान है जहाँ आप हर्ब सटर के साथ असहमत नहीं हो सकते हैं जब वह खुद को फ़ेंकने की युक्ति के बारे में झूठा विरोधाभास करता है।
जिज्ञासु

5
@curiousguy: C ++ वही है जो मानक कहता है, न कि इंटरनेट पर एक यादृच्छिक आदमी जो कहता है। तो हाँ, मानक के अनुरूप होना चाहिए । C ++ एक खुला दर्शन नहीं है जहाँ आप ऐसी किसी भी चीज़ के बारे में बात कर सकते हैं जो मानक के अनुरूप नहीं है ।
नवाज

3
"मैंने साबित किया कि कोई भी C ++ प्रोग्राम अच्छी तरह से परिभाषित व्यवहार नहीं कर सकता है।" । बिना किसी प्रमाण के लंबा दावा!
नवाज

जवाबों:


2204

सबसे पहले, आपको एक भाषा वकील की तरह सोचना सीखना होगा।

C ++ विनिर्देशन किसी विशेष संकलक, ऑपरेटिंग सिस्टम, या CPU का संदर्भ नहीं देता है। यह एक अमूर्त मशीन का संदर्भ देता है जो वास्तविक प्रणालियों का एक सामान्यीकरण है। भाषा वकील की दुनिया में, प्रोग्रामर का काम अमूर्त मशीन के लिए कोड लिखना है; संकलक का काम उस कोड को एक ठोस मशीन पर साकार करना है। युक्ति से कठोरता से कोड करके, आप निश्चित हो सकते हैं कि आपका कोड किसी भी सिस्टम पर किसी भी सिस्टम पर संशोधन के बिना संकलित और चला जाएगा, चाहे वह आज से या आज से 50 साल पहले हो।

C ++ 98 / C ++ 03 विनिर्देशन में सार मशीन मौलिक रूप से एकल-थ्रेडेड है। इसलिए बहु-थ्रेडेड सी ++ कोड लिखना संभव नहीं है जो कि कल्पना के संबंध में "पूरी तरह से पोर्टेबल" है। कल्पना भी मेमोरी लोड और स्टोर की परमाणुता के बारे में कुछ भी नहीं कहती है या जिस क्रम में लोड और स्टोर हो सकता है, म्यूटेक्स जैसी चीजों का कभी भी ध्यान न रखें।

बेशक, आप विशेष रूप से कंक्रीट सिस्टम के लिए बहु-थ्रेडेड कोड लिख सकते हैं - जैसे कि पीथ्रेड या विंडोज। लेकिन C ++ 98 / C ++ 03 के लिए बहु-थ्रेडेड कोड लिखने का कोई मानक तरीका नहीं है ।

C ++ 11 में सार मशीन डिजाइन द्वारा बहु-थ्रेडेड है। इसमें एक अच्छी तरह से परिभाषित मेमोरी मॉडल भी है ; यह है, यह कहता है कि संकलक क्या कर सकता है और जब यह स्मृति तक पहुँचने की बात नहीं करता है।

निम्नलिखित उदाहरण पर विचार करें, जहां वैश्विक चर की एक जोड़ी को दो धागे से समवर्ती रूप से एक्सेस किया जाता है:

           Global
           int x, y;

Thread 1            Thread 2
x = 17;             cout << y << " ";
y = 37;             cout << x << endl;

थ्रेड 2 आउटपुट क्या हो सकता है?

C ++ 98 / C ++ 03 के तहत, यह अपरिभाषित व्यवहार भी नहीं है; प्रश्न ही निरर्थक है क्योंकि मानक किसी भी चीज को "थ्रेड" नहीं कहता है।

सी ++ 11 के तहत, परिणाम अपरिभाषित व्यवहार है, क्योंकि लोड और स्टोर को सामान्य रूप से परमाणु नहीं होना चाहिए। जो एक बहुत सुधार की तरह नहीं लग सकता है ... और अपने आप से, यह नहीं है।

लेकिन C ++ 11 के साथ, आप इसे लिख सकते हैं:

           Global
           atomic<int> x, y;

Thread 1                 Thread 2
x.store(17);             cout << y.load() << " ";
y.store(37);             cout << x.load() << endl;

अब चीजें बहुत अधिक दिलचस्प हो गई हैं। सबसे पहले, यहां व्यवहार को परिभाषित किया गया है । थ्रेड 2 अब प्रिंट कर सकता है 0 0(यदि यह थ्रेड 1 से पहले चलता है), 37 17(यदि यह थ्रेड 1 के बाद चलता है), या 0 17(यदि थ्रेड 1 के बाद चलता है तो x पर असाइन होता है, लेकिन इससे पहले कि यह y को असाइन करता है)।

यह क्या प्रिंट नहीं कर सकता है 37 0, क्योंकि सी ++ 11 में परमाणु भार / स्टोर के लिए डिफ़ॉल्ट मोड अनुक्रमिक स्थिरता को लागू करना है । इसका मतलब यह है कि सभी लोड और स्टोर "होने चाहिए" जैसे कि वे उस क्रम में हुए थे जो आपने उन्हें प्रत्येक थ्रेड के भीतर लिखा था, जबकि थ्रेड के बीच संचालन को इंटरलेय किया जा सकता है, हालांकि सिस्टम पसंद करता है। अतः परमाणु का डिफ़ॉल्ट व्यवहार परमाणु और भार और भंडार दोनों के लिए आदेश प्रदान करता है।

अब, एक आधुनिक सीपीयू पर, क्रमिक स्थिरता सुनिश्चित करना महंगा हो सकता है। विशेष रूप से, कंपाइलर यहां हर पहुंच के बीच फुल-मेमोरी मेमोरी बाधाओं का उत्सर्जन करने की संभावना है। लेकिन अगर आपका एल्गोरिथ्म आउट-ऑफ-ऑर्डर लोड और स्टोर को सहन कर सकता है; यानी, अगर इसके लिए परमाणुता की आवश्यकता है, लेकिन आदेश देने की नहीं; अर्थात, यदि यह 37 0इस प्रोग्राम से आउटपुट के रूप में सहन कर सकता है , तो आप इसे लिख सकते हैं:

           Global
           atomic<int> x, y;

Thread 1                            Thread 2
x.store(17,memory_order_relaxed);   cout << y.load(memory_order_relaxed) << " ";
y.store(37,memory_order_relaxed);   cout << x.load(memory_order_relaxed) << endl;

सीपीयू जितना आधुनिक होगा, उतनी ही संभावना पिछले उदाहरण की तुलना में तेज होगी।

अंत में, यदि आपको केवल विशेष लोड और स्टोर रखने की आवश्यकता है, तो आप लिख सकते हैं:

           Global
           atomic<int> x, y;

Thread 1                            Thread 2
x.store(17,memory_order_release);   cout << y.load(memory_order_acquire) << " ";
y.store(37,memory_order_release);   cout << x.load(memory_order_acquire) << endl;

यह हमें आदेशित भार और दुकानों में वापस ले जाता है - इसलिए 37 0अब संभव उत्पादन नहीं है - लेकिन यह न्यूनतम ओवरहेड के साथ ऐसा करता है। (इस तुच्छ उदाहरण में, परिणाम पूर्ण विकसित अनुक्रमिक स्थिरता के समान है; एक बड़े कार्यक्रम में, यह नहीं होगा।)

बेशक, यदि केवल आउटपुट आप देखना चाहते हैं 0 0या 37 17, आप मूल कोड के चारों ओर म्यूटेक्स लपेट सकते हैं। लेकिन अगर आपने इसे पढ़ा है, तो मुझे यकीन है कि आप पहले से ही जानते हैं कि यह कैसे काम करता है, और यह उत्तर पहले से अधिक लंबा है जैसा कि मेरा इरादा है :-)।

तो, नीचे की रेखा। म्यूटेक्स महान हैं, और सी ++ 11 उन्हें मानकीकृत करता है। लेकिन कभी-कभी प्रदर्शन के कारणों से आप निचले स्तर के आदिम (उदाहरण के लिए, क्लासिक डबल-चेकिंग लॉकिंग पैटर्न ) चाहते हैं। नया मानक म्यूटेक्स और कंडीशन वैरिएबल्स जैसे उच्च-स्तरीय गैजेट प्रदान करता है, और यह निम्न-स्तरीय गैजेट जैसे परमाणु प्रकार और मेमोरी अवरोध के विभिन्न स्वाद भी प्रदान करता है। तो अब आप मानक द्वारा निर्दिष्ट भाषा के भीतर परिष्कृत, उच्च-प्रदर्शन समवर्ती दिनचर्या लिख ​​सकते हैं, और आप निश्चित हो सकते हैं कि आपका कोड आज के सिस्टम और कल दोनों पर अपरिवर्तित होगा।

हालांकि फ्रैंक होने के लिए, जब तक आप एक विशेषज्ञ नहीं हैं और कुछ गंभीर निम्न-स्तर के कोड पर काम कर रहे हैं, तो आपको संभवतः म्यूटेक्स और कंडीशन चर पर चिपकना चाहिए। यही मेरा इरादा है।

इस सामान पर अधिक जानकारी के लिए, इस ब्लॉग पोस्ट को देखें ।


37
अच्छा जवाब, लेकिन यह वास्तव में नए आदिम के कुछ वास्तविक उदाहरणों के लिए भीख माँग रहा है। इसके अलावा, मुझे लगता है कि आदिम के बिना मेमोरी ऑर्डर प्री-सी ++ 0x के समान है: कोई गारंटी नहीं है।
जॉन रिप्ले

5
@ जॉन: मुझे पता है, लेकिन मैं अभी भी प्राथमिकताओं को खुद ही सीख रहा हूं :-)। इसके अलावा मुझे लगता है कि वे गारंटी देते हैं कि बाइट एक्सेस परमाणु हैं (हालांकि आदेश नहीं दिए गए) यही कारण है कि मैं अपने उदाहरण के लिए "चार" के साथ गया था ... लेकिन मैं उस बारे में 100% भी निश्चित नहीं हूं ... यदि आप कोई अच्छा सुझाव देना चाहते हैं तो " ट्यूटोरियल "संदर्भ मैं उन्हें अपने जवाब में
निमो

48
@ नवाज़: हाँ! मेमोरी एक्सेस कंपाइलर या सीपीयू द्वारा पुनः प्राप्त किया जा सकता है। के बारे में सोचो (जैसे) कैश और सट्टा लोड। जिस क्रम में सिस्टम मेमोरी हिट हो जाती है वह आपके द्वारा कोडित की गई चीज़ के समान नहीं हो सकती है। कंपाइलर और सीपीयू यह सुनिश्चित करेगा कि ऐसे पुन: क्रम एकल-थ्रेडेड कोड को न तोड़ें । बहु-थ्रेडेड कोड के लिए, "मेमोरी मॉडल" संभावित री-ऑर्डरिंग की विशेषता रखता है, और क्या होता है यदि दो धागे एक ही समय में एक ही स्थान को पढ़ते / लिखते हैं, और आप दोनों पर नियंत्रण कैसे करते हैं। एकल-थ्रेडेड कोड के लिए, स्मृति मॉडल अप्रासंगिक है।
निमो

26
@ नवाज़, @ नीमो - एक मामूली विवरण: नया मेमोरी मॉडल सिंगल-थ्रेडेड कोड इनोफ़र में प्रासंगिक है क्योंकि यह कुछ अभिव्यक्तियों की अपरिभाषितता को निर्दिष्ट करता है, जैसे कि i = i++अनुक्रम बिंदुओं की पुरानी अवधारणा को त्याग दिया गया है; नया मानक अनुक्रम-पूर्व संबंध का उपयोग करके एक ही बात को निर्दिष्ट करता है जो कि अवधारणा से पहले अधिक सामान्य अंतर-थ्रेड होता है का एक विशेष मामला है ।
JohannesD

17
@ AJG85: सी ++ 0x के मसौदे की धारा 3.6.2 में कहा गया है, "स्थिर भंडारण अवधि (3.7.1) या थ्रेड स्टोरेज अवधि (3.7.2) के साथ चर किसी भी अन्य इनिशियलाइज़ेशन से पहले शून्य-आरंभिक (8.5) होगा। जगह।" चूंकि x, y इस उदाहरण में वैश्विक हैं, इसलिए उनके पास स्थिर भंडारण अवधि है और इसलिए यह शून्य-आरंभिक होगा, मेरा मानना ​​है।
निमो

345

मैं बस उस सादृश्य को दूंगा जिसके साथ मैं मेमोरी संगतता मॉडल (या मेमोरी मॉडल, शॉर्ट के लिए) को समझता हूं। यह लेस्ली लामपोर्ट के सेमिनल पेपर "टाइम, क्लॉक्स एंड द ऑर्डरिंग ऑफ इवेंट्स इन ए डिस्ट्रीब्यूटेड सिस्टम" से प्रेरित है । सादृश्य उपयुक्त है और इसका मौलिक महत्व है, लेकिन कई लोगों के लिए यह अधिक महत्वपूर्ण हो सकता है। हालांकि, मुझे उम्मीद है कि यह एक मानसिक छवि (एक सचित्र प्रतिनिधित्व) प्रदान करता है जो स्मृति संगतता मॉडल के बारे में तर्क की सुविधा देता है।

आइए अंतरिक्ष-समय आरेख में सभी स्मृति स्थानों के इतिहास को देखें जिसमें क्षैतिज अक्ष पता स्थान का प्रतिनिधित्व करता है (यानी, प्रत्येक स्मृति स्थान उस अक्ष पर एक बिंदु द्वारा दर्शाया गया है) और ऊर्ध्वाधर अक्ष समय का प्रतिनिधित्व करता है (हम देखेंगे कि, सामान्य तौर पर, समय की सार्वभौमिक धारणा नहीं है)। इसलिए, प्रत्येक मेमोरी लोकेशन के मानों का इतिहास उस मेमोरी एड्रेस पर एक वर्टिकल कॉलम द्वारा दर्शाया जाता है। प्रत्येक मूल्य परिवर्तन उस स्थान पर एक नया मान लिखने वाले थ्रेड्स में से एक के कारण होता है। एक मेमोरी इमेज के द्वारा , हम एक विशेष थ्रेड द्वारा किसी विशेष समय में अवलोकन योग्य सभी मेमोरी स्थानों के मूल्यों के समुच्चय / संयोजन का अर्थ करेंगे ।

"मेमोरी प्राइमरी और कैश कोहेरेंस पर एक प्राइमर" से उद्धृत

सहज (और सबसे अधिक प्रतिबंधात्मक) मेमोरी मॉडल अनुक्रमिक स्थिरता (एससी) है जिसमें एक मल्टीथ्रेडेड निष्पादन को प्रत्येक घटक धागे के अनुक्रमिक निष्पादन की एक इंटरलेविंग की तरह दिखना चाहिए, जैसे कि थ्रेड्स सिंगल-कोर प्रोसेसर पर टाइम-मल्टीप्लेक्स किए गए थे।

वह वैश्विक मेमोरी ऑर्डर प्रोग्राम के एक रन से दूसरे में भिन्न हो सकता है और पहले से नहीं जाना जा सकता है। एससी की विशेषता विशेषता एड्रेस-स्पेस-टाइम डायग्राम में क्षैतिज स्लाइस का एक साथ समरूपता (यानी, मेमोरी मेमोरी) के विमानों का प्रतिनिधित्व है । किसी दिए गए विमान पर, इसकी सभी घटनाएं (या स्मृति मूल्य) एक साथ होती हैं। निरपेक्ष समय की एक धारणा है , जिसमें सभी सूत्र इस बात पर सहमत हैं कि स्मृति मूल्य एक साथ हैं। SC में, हर समय तत्काल, सभी थ्रेड्स द्वारा साझा की गई केवल एक मेमोरी छवि होती है। यही है, हर समय, सभी प्रोसेसर मेमोरी इमेज (यानी, मेमोरी की कुल सामग्री) पर सहमत होते हैं। न केवल इसका मतलब यह है कि सभी थ्रेड्स सभी मेमोरी स्थानों के लिए समान मानों को देखते हैं, बल्कि यह भी है कि सभी प्रोसेसर समान हैंसभी चर के मूल्यों का संयोजन । यह सभी मेमोरी ऑपरेशन (सभी मेमोरी स्थानों पर) सभी थ्रेड्स द्वारा एक ही कुल क्रम में देखे जाने के समान है।

आरामदायक मेमोरी मॉडल में, प्रत्येक थ्रेड अपने तरीके से एड्रेस-स्पेस-टाइम को स्लाइस करेगा, एकमात्र प्रतिबंध यह है कि प्रत्येक थ्रेड के स्लाइस एक दूसरे को पार नहीं करेंगे क्योंकि सभी थ्रेड्स को प्रत्येक व्यक्तिगत मेमोरी लोकेशन के इतिहास पर सहमत होना चाहिए (बेशक , अलग-अलग धागे के टुकड़े, और इच्छाशक्ति, एक-दूसरे को पार कर सकते हैं)। इसे स्लाइस करने का कोई सार्वभौमिक तरीका नहीं है (एड्रेस-स्पेस-टाइम का कोई विशेषाधिकार प्राप्त नहीं है)। स्लाइस को प्लेनर (या रैखिक) होने की आवश्यकता नहीं है। वे घुमावदार हो सकते हैं और यह वही है जो किसी अन्य थ्रेड द्वारा लिखे गए थ्रेड रीड वैल्यू को उनके द्वारा लिखे गए ऑर्डर से अलग कर सकता है। किसी विशेष थ्रेड द्वारा देखे जाने पर विभिन्न मेमोरी स्थानों के इतिहास एक दूसरे के सापेक्ष स्लाइड (या स्ट्रेच हो सकते हैं) हो सकते हैं।। प्रत्येक थ्रेड का एक अलग अर्थ होगा कि कौन सी घटनाएं (या, समकक्ष, स्मृति मान) एक साथ हैं। घटनाओं (या स्मृति मूल्यों) का सेट जो एक धागे से दूसरे के साथ-साथ होते हैं। इस प्रकार, एक आराम स्मृति मॉडल में, सभी थ्रेड अभी भी प्रत्येक मेमोरी स्थान के लिए एक ही इतिहास (यानी, मूल्यों का क्रम) का निरीक्षण करते हैं। लेकिन वे अलग-अलग मेमोरी छवियों (यानी, सभी मेमोरी स्थानों के मूल्यों के संयोजन) का निरीक्षण कर सकते हैं। भले ही दो अलग-अलग मेमोरी लोकेशन एक ही धागे से अनुक्रम में लिखे गए हों, दो नए लिखित मान अन्य थ्रेड्स द्वारा अलग-अलग क्रम में देखे जा सकते हैं।

[चित्र विकिपीडिया से] चित्र विकिपीडिया से

आइंस्टीन की विशेष थ्योरी ऑफ रिलेटिविटी से परिचित पाठक यह नोटिस करेंगे कि मैं किस चीज से जुड़ा हूं। मेमोरी मॉडल दायरे में मिंकोव्स्की के शब्दों का अनुवाद करना: पता स्थान और समय पते-स्थान-समय की छाया हैं। इस मामले में, प्रत्येक पर्यवेक्षक (यानी, थ्रेड) अपने स्वयं के विश्व-रेखा (यानी, उसके समय की धुरी) और एक ही समय के अपने विमान (अपने पता-स्थान अक्ष) पर घटनाओं की छाया (यानी, मेमोरी स्टोर / लोड) को प्रोजेक्ट करेगा। । C ++ 11 मेमोरी मॉडल में थ्रेड्स पर्यवेक्षकों के अनुरूप हैं जो विशेष सापेक्षता में एक दूसरे के सापेक्ष बढ़ रहे हैं। अनुक्रमिक संगतता गैलीलियन स्पेस-टाइम से मेल खाती है (यानी, सभी पर्यवेक्षक घटनाओं के एक पूर्ण आदेश और एक साथ वैश्विकता के साथ सहमत हैं)।

मेमोरी मॉडल और विशेष सापेक्षता के बीच समानता इस तथ्य से उपजी है कि दोनों घटनाओं के आंशिक रूप से क्रमबद्ध सेट को परिभाषित करते हैं, जिसे अक्सर एक कारण सेट कहा जाता है। कुछ घटनाएँ (यानी, मेमोरी स्टोर) अन्य घटनाओं को प्रभावित कर सकती हैं (लेकिन प्रभावित नहीं होती हैं)। C ++ 11 थ्रेड (या भौतिकी में प्रेक्षक) घटनाओं की एक श्रृंखला (यानी, एक पूरी तरह से आदेशित सेट) से अधिक नहीं है (उदाहरण के लिए, मेमोरी लोड और संभवतः अलग-अलग पते के लिए स्टोर)।

सापेक्षता में, कुछ आदेश आंशिक रूप से आदेशित घटनाओं की प्रतीत होती हुई अराजक तस्वीर के लिए बहाल किया जाता है, क्योंकि एकमात्र अस्थायी आदेश है कि सभी पर्यवेक्षक सहमत हैं "टाइमलीक" घटनाओं (यानी, उन घटनाओं के सिद्धांत हैं जो किसी भी कण के धीमी गति से संयोजी हैं। निर्वात में प्रकाश की गति से)। केवल समयबद्ध संबंधित घटनाओं को हमेशा आदेश दिया जाता है। फिजिक्स में समय, क्रेग कॉलेंडर

C ++ 11 मेमोरी मॉडल में, इन स्थानीय कारण संबंधों को स्थापित करने के लिए एक समान तंत्र (अधिग्रहण-रिलीज संगति मॉडल) का उपयोग किया जाता है ।

स्मृति स्थिरता की परिभाषा और SC को छोड़ने के लिए एक प्रेरणा प्रदान करने के लिए, मैं "A Primer on Memory Consistency and Cache Coherence" से उद्धृत करूंगा।

एक साझा मेमोरी मशीन के लिए, मेमोरी संगति मॉडल अपने मेमोरी सिस्टम के वास्तुशिल्प रूप से दृश्यमान व्यवहार को परिभाषित करता है। " एक सही परिणाम " और " कई गलत विकल्पों " के बीच एकल प्रोसेसर कोर विभाजन व्यवहार के लिए शुद्धता मानदंड । ऐसा इसलिए है क्योंकि प्रोसेसर का आर्किटेक्चर यह बताता है कि एक थ्रेड का निष्पादन किसी दिए गए इनपुट स्टेट को सिंगल-डिफाइंड आउटपुट स्टेट में बदल देता है, यहां तक ​​कि आउट-ऑफ-ऑर्डर कोर पर भी। हालाँकि, साझा मेमोरी संगतता मॉडल, कई थ्रेड्स के लोड और स्टोर की चिंता करते हैं और आमतौर पर कई सही निष्पादन की अनुमति देते हैंकई (अधिक) गलत लोगों को हटाते समय। कई सही निष्पादन की संभावना आईएसए के कारण कई सूत्र समवर्ती रूप से निष्पादित करने की अनुमति देते हैं, अक्सर विभिन्न थ्रेड्स से निर्देशों के कई संभावित कानूनी हस्तक्षेप के साथ।

आराम से या कमजोर मेमोरी संगतता मॉडल इस तथ्य से प्रेरित होते हैं कि मजबूत मॉडल में अधिकांश मेमोरी ऑर्डर अनावश्यक हैं। यदि कोई थ्रेड दस डेटा आइटम्स और फिर एक सिंक्रनाइज़ेशन फ़्लैग को अपडेट करता है, तो प्रोग्रामर आमतौर पर इस बात की परवाह नहीं करते हैं कि डेटा आइटम्स को एक-दूसरे के संबंध में अपडेट किया जाता है, लेकिन केवल यह कि फ़्लैग अपडेट होने से पहले सभी डेटा आइटम अपडेट हो जाते हैं (आमतौर पर FENCE निर्देशों का उपयोग करके लागू किया जाता है) )। आराम करने वाले मॉडल इस बढ़ते हुए लचीलेपन को पकड़ना चाहते हैं और केवल उन आदेशों को संरक्षित करते हैं जो प्रोग्रामर की आवश्यकता होती है“SC के उच्च प्रदर्शन और शुद्धता दोनों को प्राप्त करने के लिए। उदाहरण के लिए, कुछ आर्किटेक्चर में, एफआईएफओ राइट बफ़र्स का उपयोग प्रत्येक कोर द्वारा कैशर्स को परिणाम लिखने से पहले प्रतिबद्ध (सेवानिवृत्त) स्टोर के परिणामों को रखने के लिए किया जाता है। यह अनुकूलन प्रदर्शन को बढ़ाता है लेकिन SC का उल्लंघन करता है। लेखन बफर एक स्टोर मिस सर्विसिंग की विलंबता को छिपाता है। क्योंकि स्टोर आम हैं, उनमें से अधिकांश पर स्टालिंग से बचने में सक्षम होना एक महत्वपूर्ण लाभ है। सिंगल-कोर प्रोसेसर के लिए, एक लिखित बफ़र को यह सुनिश्चित करके वास्तुशिल्प रूप से अदृश्य बनाया जा सकता है कि ए को संबोधित करने के लिए लोड ए में सबसे हाल के स्टोर का मान लौटाता है, भले ही ए या एक से अधिक स्टोर राइट बफ़र में हों। यह आमतौर पर ए से लोड करने के लिए ए के लिए सबसे हाल के स्टोर के मूल्य को दरकिनार करके किया जाता है, जहां "सबसे हाल का" प्रोग्राम ऑर्डर द्वारा निर्धारित किया जाता है, या ए के भार को रोक कर यदि ए से ए स्टोर राइट बफर में है। जब कई कोर का उपयोग किया जाता है, तो प्रत्येक का अपना बायपास राइटिंग बफर होगा। लिखने वाले बफ़र्स के बिना, हार्डवेयर SC है, लेकिन लिखने वाले बफ़र्स के साथ, यह ऐसा नहीं है, जिससे मल्टीकोर प्रोसेसर में बफ़र्स को आर्किटेक्चरली दिखाई दे।

स्टोर-स्टोर रीऑर्डरिंग तब हो सकता है यदि किसी कोर में गैर-फीफो लिखने वाला बफर होता है जो स्टोरों को उस क्रम से अलग क्रम में प्रस्थान करने देता है जिसमें वे दर्ज हुए थे। यह तब हो सकता है जब पहला स्टोर कैश में छूट जाता है जबकि दूसरा हिट होता है या यदि दूसरा स्टोर पहले के स्टोर (यानी, पहले स्टोर से पहले) के साथ मिल सकता है। लोड-लोड रीऑर्डरिंग डायनामिक-शेड्यूल किए गए कोर पर भी हो सकता है जो प्रोग्राम ऑर्डर से निर्देशों को निष्पादित करते हैं। कि एक और कोर पर भंडार reordering के रूप में ही व्यवहार कर सकते हैं (आप दो धागे के बीच एक उदाहरण interleaving के साथ आ सकता है?)। बाद के स्टोर (लोड-स्टोर री-लोडिंग) के साथ पहले के लोड को फिर से व्यवस्थित करना कई गलत व्यवहारों का कारण बन सकता है, जैसे कि लॉक को जारी करने के बाद एक मूल्य लोड करना जो इसे बचाता है (यदि स्टोर अनलॉक ऑपरेशन है)।

क्योंकि कैश सुसंगतता और मेमोरी की संगति कभी-कभी भ्रमित हो जाती है, यह निर्देशात्मक है कि यह उद्धरण भी है:

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

हमारी मानसिक तस्वीर के साथ जारी रखते हुए, SWMR आक्रमणकर्ता भौतिक आवश्यकता से मेल खाता है कि किसी एक स्थान पर सबसे अधिक एक कण स्थित है, लेकिन किसी भी स्थान के पर्यवेक्षकों की एक असीमित संख्या हो सकती है।


52
विशेष सापेक्षता के साथ सादृश्य के लिए +1, मैं खुद को उसी अनुरूप बनाने की कोशिश कर रहा हूं। बहुत बार मैं प्रोग्रामर को थ्रेडेड कोड की जांच करते हुए व्यवहार की व्याख्या करने की कोशिश करते हुए देखता हूं कि एक विशिष्ट क्रम में एक दूसरे के साथ जुड़े हुए अलग-अलग थ्रेड्स में ऑपरेशन होते हैं, और मुझे उन्हें बताना होगा, नहीं, मल्टी-प्रोसेसर सिस्टम के साथ एक साथ अलग-अलग धारणाओं की धारणा > संदर्भ के फ्रेम </ b> धागे अब अर्थहीन हैं। विशेष सापेक्षता के साथ तुलना करना उन्हें समस्या की जटिलता का सम्मान करने का एक अच्छा तरीका है।
पियरे लेबेपिन

71
तो क्या आपको यह निष्कर्ष निकालना चाहिए कि यूनिवर्स मल्टीकोर है?
पीटर के

6
@PeterK: बिल्कुल :) और यहां भौतिक विज्ञानी ब्रायन ग्रीन द्वारा समय की इस तस्वीर का एक बहुत अच्छा दृश्य है: youtube.com/watch?v=4BjGWLJNPcA&t=22m12s यह "भ्रम का समय है [पूर्ण वृत्तचित्र]" 22 मिनट और मिनट पर 12 सेकंड।
अहमद नासर

2
क्या यह सिर्फ मुझे है या वह 1 डी मेमोरी मॉडल (क्षैतिज अक्ष) से ​​2 डी मेमोरी मॉडल (एक साथ विमानों के विमानों) पर स्विच कर रहा है। मुझे यह थोड़ा उलझा हुआ लगता है लेकिन शायद ऐसा इसलिए है क्योंकि मैं एक देशी वक्ता नहीं हूं ... फिर भी एक बहुत ही दिलचस्प पाठ है।
गुडबाय एसई

आप एक आवश्यक हिस्सा भूल गए: " लोड और स्टोर के परिणामों का विश्लेषण करके " ... सटीक समय की जानकारी का उपयोग किए बिना।
जिज्ञासु

115

यह अब एक बहु-वर्षीय प्रश्न है, लेकिन बहुत लोकप्रिय होने के नाते, यह C ++ 11 मेमोरी मॉडल के बारे में सीखने के लिए एक शानदार संसाधन का उल्लेख करने योग्य है। मुझे इस बात का कोई मतलब नहीं दिख रहा है कि यह एक और पूर्ण उत्तर देने के लिए है, लेकिन यह वह आदमी है जिसने वास्तव में मानक लिखा है, मुझे लगता है कि यह बात देखने लायक है।

हर्ब सटर ने C ++ 11 मेमोरी मॉडल के बारे में तीन घंटे लंबी बात की है, जिसका शीर्षक "परमाणु <> हथियार" है, जो Channel9 साइट पर उपलब्ध है - भाग 1 और भाग 2 । बात काफी तकनीकी है, और निम्नलिखित विषयों को शामिल किया गया है:

  1. अनुकूलन, दौड़, और मेमोरी मॉडल
  2. आदेश देना - क्या: प्राप्त करें और जारी करें
  3. आदेश देना - कैसे: म्यूटेक्स, एटमिक्स, और / या बाड़
  4. कंपाइलर और हार्डवेयर पर अन्य प्रतिबंध
  5. कोड जनरल और प्रदर्शन: x86 / x64, IA64, POWER, ARM
  6. आराम से एटमिक्स

बात एपीआई पर विस्तृत नहीं है, बल्कि तर्क, पृष्ठभूमि पर, हुड के नीचे और पर्दे के पीछे (क्या आप जानते हैं कि आराम से शब्दार्थ केवल मानक में जोड़े गए थे क्योंकि पावर और एआरएम सिंक्रनाइज़ लोड को कुशलता से समर्थन नहीं करते हैं?)।


10
यह बात वास्तव में शानदार है, पूरी तरह से 3 घंटे के लायक आप इसे देखने में खर्च करेंगे।
ज़ुनत्ज़ु

5
@ZunTzu: अधिकांश वीडियो खिलाड़ियों पर आप 1.25, 1.5 या 2 गुना मूल गति सेट कर सकते हैं।
क्रिश्चियन सेवेरिन

4
@eran क्या आप लोग स्लाइड्स के लिए होते हैं? चैनल 9 टॉक पेज के लिंक काम नहीं करते हैं।
एथोस 30/16

2
@athos मेरे पास नहीं है, क्षमा करें। चैनल 9 से संपर्क करने का प्रयास करें, मुझे नहीं लगता कि निष्कासन जानबूझकर था (मेरा अनुमान है कि उन्हें हर्ब सटर से लिंक मिला है, जैसा कि पोस्ट किया गया है, और उन्होंने बाद में फाइलें हटा दीं; लेकिन यह सिर्फ एक अटकल है ...)।
एर

75

इसका मतलब है कि मानक अब मल्टी-थ्रेडिंग को परिभाषित करता है, और यह परिभाषित करता है कि कई थ्रेड्स के संदर्भ में क्या होता है। बेशक, लोग अलग-अलग कार्यान्वयन का उपयोग करते थे, लेकिन यह पूछने की तरह है कि हमारे पास ऐसा क्यों होना चाहिए std::stringजब हम सभी एक घर-लुढ़का stringवर्ग का उपयोग कर सकते हैं ।

जब आप पोसिक्स थ्रेड्स या विंडोज थ्रेड्स के बारे में बात कर रहे होते हैं, तो यह एक भ्रम है, क्योंकि वास्तव में आप x86 थ्रेड्स के बारे में बात कर रहे हैं, क्योंकि यह समवर्ती रूप से चलाने के लिए एक हार्डवेयर फ़ंक्शन है। C ++ 0x मेमोरी मॉडल गारंटी देता है, चाहे आप x86 पर हों, या ARM, या MIPS , या कुछ और जो आप के साथ आ सकते हैं।


28
पॉज़िक्स धागे x86 तक सीमित नहीं हैं। वास्तव में, पहले सिस्टम जिन पर उन्हें लागू किया गया था, शायद x86 सिस्टम नहीं थे। पॉज़िक्स थ्रेड सिस्टम-स्वतंत्र हैं, और सभी पॉज़िक्स प्लेटफ़ॉर्म पर मान्य हैं। यह भी वास्तव में सच नहीं है कि यह एक हार्डवेयर संपत्ति है क्योंकि पॉज़िक्स थ्रेड्स को सहकारी मल्टीटास्किंग के माध्यम से भी लागू किया जा सकता है। लेकिन बेशक ज्यादातर थ्रेडिंग मुद्दे केवल हार्डवेयर थ्रेडिंग कार्यान्वयन पर सतह (और कुछ केवल मल्टीप्रोसेसर / मल्टीकोर सिस्टम पर)।
celtschk 19

57

मेमोरी मॉडल निर्दिष्ट नहीं करने वाली भाषाओं के लिए, आप प्रोसेसर आर्किटेक्चर द्वारा निर्दिष्ट भाषा और मेमोरी मॉडल के लिए कोड लिख रहे हैं । प्रोसेसर प्रदर्शन के लिए मेमोरी एक्सेस को फिर से ऑर्डर करने का विकल्प चुन सकता है। इसलिए, यदि आपके प्रोग्राम में डेटा रेस है (एक डेटा रेस तब होती है जब एक ही मेमोरी को एक समान मेमोरी में एक्सेस करने के लिए कई कोर / हाइपर-थ्रेड्स के लिए संभव हो) तो प्रोसेसर मेमोरी मॉडल पर निर्भर होने के कारण आपका प्रोग्राम क्रॉस प्लेटफॉर्म नहीं है। आप मेमोरी को एक्सेस करने के लिए प्रोसेसर को कैसे ऑर्डर कर सकते हैं, यह जानने के लिए आप इंटेल या एएमडी सॉफ्टवेयर मैनुअल का उल्लेख कर सकते हैं।

बहुत महत्वपूर्ण बात, ताले (और लॉकिंग के साथ संगामिति शब्द) आमतौर पर एक क्रॉस प्लेटफॉर्म तरीके से लागू किए जाते हैं ... इसलिए यदि आप बिना डेटा दौड़ वाले एक मल्टीथ्रेड प्रोग्राम में मानक ताले का उपयोग कर रहे हैं, तो आपको क्रॉस प्लेटफॉर्म मेमोरी मॉडल के बारे में चिंता करने की ज़रूरत नहीं है

दिलचस्प बात यह है कि C ++ के लिए Microsoft कंपाइलरों ने वाष्पशील के लिए सिमेंटिक्स प्राप्त / विमोचन किया है जो C ++ में एक मेमोरी मॉडल की कमी से निपटने के लिए C ++ एक्सटेंशन है। http://msdn.microsoft.com/en-us/library/12a04hhd(v=vs .80) .aspx । हालाँकि, यह देखते हुए कि विंडोज केवल x86 / x64 पर चलता है, यह बहुत कुछ नहीं कह रहा है (इंटेल और एएमडी मेमोरी मॉडल एक भाषा में अधिग्रहण / रिलीज शब्द को लागू करने के लिए आसान और कुशल बनाते हैं)।


2
यह सच है कि, जब उत्तर लिखा गया था, तो विंडोज़ x86 / x64 पर ही चलता है, लेकिन विंडोज़ कुछ समय में, IA64, MIPS, अल्फा AXP64, PowerPC और ARM पर चलता है। आज यह एआरएम के विभिन्न संस्करणों पर चलता है, जो कि x86 से काफी अलग मेमोरी वार है, और लगभग माफ करने के रूप में कहीं नहीं है।
लोरेंजो डेमेटे

वह लिंक कुछ हद तक टूटा हुआ है ( "विजुअल स्टूडियो 2005 रिटायर्ड डॉक्यूमेंटेशन" )। इसे अद्यतन करने के लिए देखभाल?
पीटर मोर्टेंसन

3
उत्तर लिखे जाने पर भी यह सच नहीं था।
बेन

" एक ही स्मृति को समवर्ती रूप से उपयोग करने के लिए" एक परस्पर विरोधी तरीके से उपयोग करने के लिए
curiousguy

27

यदि आप अपने सभी डेटा की सुरक्षा के लिए म्यूटेक्स का उपयोग करते हैं, तो आपको वास्तव में चिंता करने की आवश्यकता नहीं है। म्यूटेक्स ने हमेशा पर्याप्त ऑर्डरिंग और दृश्यता की गारंटी प्रदान की है।

अब, यदि आपने एटॉमिक्स, या लॉक-फ्री एल्गोरिदम का उपयोग किया है, तो आपको मेमोरी मॉडल के बारे में सोचने की आवश्यकता है। स्मृति मॉडल ठीक-ठीक वर्णन करता है जब एटोमिक्स ऑर्डरिंग और दृश्यता की गारंटी प्रदान करता है, और हाथ से कोडित गारंटी के लिए पोर्टेबल बाड़ प्रदान करता है।

पहले, एटमिक्स कंपाइलर इंट्रिनिक्स, या कुछ उच्च स्तर के पुस्तकालय का उपयोग करके किया जाएगा। सीपीयू-विशिष्ट निर्देशों (मेमोरी बैरियर्स) का उपयोग करके बाड़ लगाए गए होंगे।


19
पहले समस्या यह थी कि म्यूटेक्स (सी ++ मानक के संदर्भ में) जैसी कोई चीज नहीं थी। इसलिए आपको प्रदान की गई एकमात्र गारंटी म्यूटेक्स निर्माता द्वारा दी गई थी, जो तब तक ठीक थी जब तक आपने कोड को पोर्ट नहीं किया था (जैसा कि गारंटी में मामूली परिवर्तन स्पॉट के लिए कठिन है)। अब हमें मानक द्वारा प्रदान की जाने वाली गारंटी मिलती है जो प्लेटफार्मों के बीच पोर्टेबल होनी चाहिए।
मार्टिन यॉर्क

4
@ मर्टिन: किसी भी मामले में, एक चीज़ मेमोरी मॉडल है, और दूसरे एटमिक्स और थ्रेडिंग प्राइमेटिक्स हैं जो उस मेमोरी मॉडल के शीर्ष पर चलते हैं।
निंलज

4
इसके अलावा, मेरी बात यह थी कि पहले भाषा स्तर पर ज्यादातर मेमोरी मॉडल नहीं था, यह अंतर्निहित सीपीयू का मेमोरी मॉडल था। अब एक मेमोरी मॉडल है जो मूल भाषा का हिस्सा है; OTOH, म्यूटेक्स और लाइक हमेशा एक पुस्तकालय के रूप में किया जा सकता है।
नंजलज

3
म्यूटेक्स लाइब्रेरी लिखने की कोशिश कर रहे लोगों के लिए यह एक वास्तविक समस्या हो सकती है । जब CPU, मेमोरी कंट्रोलर, कर्नेल, कंपाइलर और "C लाइब्रेरी" सभी को अलग-अलग टीमों द्वारा लागू किया जाता है, और उनमें से कुछ हिंसक असहमति में होते हैं कि यह सामान कैसे काम करना चाहिए, ठीक है, कभी-कभी सामान हम सिस्टम प्रोग्रामर को अनुप्रयोगों के स्तर के लिए एक सुंदर मुखौटा पेश करना है, यह बिल्कुल भी सुखद नहीं है।
zwol

11
दुर्भाग्य से यह सरल म्यूटेक्स के साथ आपकी डेटा संरचनाओं की रक्षा करने के लिए पर्याप्त नहीं है अगर आपकी भाषा में एक सुसंगत मेमोरी मॉडल नहीं है। विभिन्न कंपाइलर ऑप्टिमाइज़ेशन हैं जो एक ही थ्रेडेड संदर्भ में समझ में आते हैं, लेकिन जब कई थ्रेड्स और सीपीयू कोर खेलने में आते हैं, तो मेमोरी एक्सेस और अन्य ऑप्टिमाइज़ेशन का पुन: निर्धारण अपरिभाषित व्यवहार उत्पन्न कर सकता है। अधिक जानकारी के लिए हंस बोएहम
exDM69

0

उपरोक्त उत्तर C ++ मेमोरी मॉडल के सबसे बुनियादी पहलुओं पर मिलते हैं। व्यवहार में, std::atomic<>"बस काम" के अधिकांश उपयोग , कम से कम जब तक प्रोग्रामर अधिक-अनुकूलन नहीं करता (उदाहरण के लिए, बहुत सी चीजों को आराम करने की कोशिश करके)।

एक जगह है जहाँ गलतियाँ अभी भी आम हैं: अनुक्रम तालेHttps://www.hpl.hp.com/techreports/2012/HPL-2012-68.pdf पर चुनौतियों की एक उत्कृष्ट और आसानी से पढ़ी जाने वाली चर्चा है । अनुक्रम ताले आकर्षक लग रहे हैं क्योंकि पाठक लॉक शब्द को लिखने से बचता है। निम्नलिखित कोड उपरोक्त तकनीकी रिपोर्ट के चित्र 1 पर आधारित है, और यह सी ++ में अनुक्रम ताले को लागू करते समय चुनौतियों पर प्रकाश डालता है:

atomic<uint64_t> seq; // seqlock representation
int data1, data2;     // this data will be protected by seq

T reader() {
    int r1, r2;
    unsigned seq0, seq1;
    while (true) {
        seq0 = seq;
        r1 = data1; // INCORRECT! Data Race!
        r2 = data2; // INCORRECT!
        seq1 = seq;

        // if the lock didn't change while I was reading, and
        // the lock wasn't held while I was reading, then my
        // reads should be valid
        if (seq0 == seq1 && !(seq0 & 1))
            break;
    }
    use(r1, r2);
}

void writer(int new_data1, int new_data2) {
    unsigned seq0 = seq;
    while (true) {
        if ((!(seq0 & 1)) && seq.compare_exchange_weak(seq0, seq0 + 1))
            break; // atomically moving the lock from even to odd is an acquire
    }
    data1 = new_data1;
    data2 = new_data2;
    seq = seq0 + 2; // release the lock by increasing its value to even
}

के रूप में unintuitive के रूप में यह पहली बार में तेजी, data1और होने की data2जरूरत है atomic<>। यदि वे परमाणु नहीं हैं, तो वे reader()ठीक उसी समय पढ़े जा सकते हैं ( जब वे लिखे गए हों writer())। C ++ मेमोरी मॉडल के अनुसार, यह एक दौड़ है भले ही reader()वह वास्तव में डेटा का उपयोग न करता हो । इसके अलावा, यदि वे परमाणु नहीं हैं, तो संकलक प्रत्येक मूल्य के पहले रीड को एक रजिस्टर में कैश कर सकता है। जाहिर है आप ऐसा नहीं चाहेंगे ... आप whileलूप के प्रत्येक पुनरावृत्ति में फिर से पढ़ना चाहते हैं reader()

उन्हें बनाना atomic<>और उनके साथ पहुंच बनाना भी पर्याप्त नहीं है memory_order_relaxed। इसका कारण यह है कि seq (in reader()) के रीड्स ने केवल शब्दार्थ का अधिग्रहण किया है। सरल शब्दों में, यदि एक्स और वाई मेमोरी एक्सेस हैं, तो एक्स प्री वाई है, एक्स कोई अधिग्रहण या रिलीज नहीं है, और वाई एक अधिग्रहण है, तो कंपाइलर एक्स से पहले वाई को फिर से चालू कर सकता है। अगर वाई सीक का दूसरा पढ़ा था, और एक्स। डेटा का एक पाठ था, इस तरह के एक पुनरावृत्ति ताला कार्यान्वयन को तोड़ देगा।

कागज कुछ समाधान देता है। आज सबसे अच्छा प्रदर्शन वाला व्यक्ति शायद वह है जो selock के दूसरे पढ़ने से पहले के atomic_thread_fenceसाथ उपयोग करता है । कागज में, यह चित्रा 6 है। मैं यहां कोड को पुन: प्रस्तुत नहीं कर रहा हूं, क्योंकि जिसने भी इसे पढ़ा है वह वास्तव में कागज को पढ़ना चाहिए। यह इस पद की तुलना में अधिक सटीक और पूर्ण है।memory_order_relaxed

अंतिम मुद्दा यह है कि dataचर को परमाणु बनाना अस्वाभाविक हो सकता है । यदि आप अपने कोड में नहीं जा सकते हैं, तो आपको बहुत सावधानी बरतने की आवश्यकता है, क्योंकि गैर-परमाणु से परमाणु तक की कास्टिंग केवल आदिम प्रकारों के लिए कानूनी है। C ++ 20 को जोड़ना है atomic_ref<>, जिससे इस समस्या को हल करना आसान हो जाएगा।

संक्षेप में: यदि आपको लगता है कि आप C ++ मेमोरी मॉडल को समझते हैं, तो आपको अपने स्वयं के अनुक्रम ताले को रोल करने से पहले बहुत सावधान रहना चाहिए।


-2

C और C ++ को एक अच्छी तरह से बने प्रोग्राम के निष्पादन ट्रेस द्वारा परिभाषित किया जाता था।

अब वे एक कार्यक्रम के निष्पादन ट्रेस द्वारा आधा परिभाषित किए जाते हैं, और सिंक्रनाइज़ेशन ऑब्जेक्ट्स पर कई आदेशों द्वारा आधा पोस्टीरियर।

मतलब यह है कि ये भाषा परिभाषाएं इन दोनों दृष्टिकोणों को मिलाने के लिए कोई तार्किक विधि नहीं है। विशेष रूप से, म्यूटेक्स या परमाणु चर का विनाश अच्छी तरह से परिभाषित नहीं है।


मैं भाषा डिजाइन में सुधार के लिए आपकी भयंकर इच्छा साझा करता हूं, लेकिन मुझे लगता है कि आपका उत्तर अधिक मूल्यवान होगा यदि यह एक साधारण मामले पर केंद्रित था, जिसके लिए आपने स्पष्ट रूप से और स्पष्ट रूप से दिखाया कि कैसे व्यवहार विशिष्ट भाषा डिजाइन सिद्धांतों का उल्लंघन करता है। उसके बाद मैं दृढ़ता से आप की सिफारिश करेंगे, अगर तुम मुझे अनुमति देते हैं, कि इस सवाल का जवाब में उन बिंदुओं में से प्रत्येक की प्रासंगिकता के लिए एक बहुत अच्छा तर्क, देने के लिए, क्योंकि वे inmense उत्पादकता सी ++ डिजाइन द्वारा कथित लाभ की प्रासंगिकता के खिलाफ विषम हो जाएगा
मटीस

1
@MatiasHaeussler मुझे लगता है कि आपने मेरे उत्तर को गलत बताया है; मैं यहाँ एक विशेष C ++ फीचर की परिभाषा पर आपत्ति नहीं कर रहा हूँ (मेरी भी ऐसी कई आलोचनाएँ हैं लेकिन यहाँ नहीं)। मैं यहाँ तर्क दे रहा हूँ कि C ++ (न ही C) में कोई अच्छी तरह से परिभाषित निर्माण नहीं है। पूरे एमटी शब्दार्थ एक संपूर्ण गड़बड़ हैं, क्योंकि आपके पास अब अनुक्रमिक शब्दार्थ नहीं हैं। (मेरा मानना ​​है कि जावा एमटी टूट गया है लेकिन कम है।) "सरल उदाहरण" लगभग किसी भी एमटी कार्यक्रम होगा। यदि आप असहमत हैं, तो एमटी सी ++ कार्यक्रमों की शुद्धता साबित करने के बारे में मेरे सवाल का जवाब देने के लिए आपका स्वागत है ।
जिज्ञासु

दिलचस्प है, मुझे लगता है कि मैं आपके प्रश्न को पढ़ने के बाद आपके बारे में अधिक समझता हूं। यदि मैं सही हूं तो आप C ++ MT कार्यक्रमों की शुद्धता के लिए प्रमाण विकसित करने की असंभवता का उल्लेख कर रहे हैं । ऐसे में मैं कहूंगा कि मेरे लिए कंप्यूटर प्रोग्रामिंग के भविष्य के लिए बहुत बड़ा महत्व है, विशेष रूप से कृत्रिम बुद्धिमत्ता के आगमन के लिए। लेकिन मैं यह भी कहना चाहूंगा कि बहुत से लोगों के लिए स्टैक ओवरफ्लो में सवाल पूछना कुछ ऐसा नहीं है, जिसके बारे में वे जानते भी नहीं हैं, और यह समझने के बाद भी कि आपका क्या मतलब है और क्या दिलचस्पी है
मतिस ह्युसलर

1
"क्या कंप्यूटर प्रोग्राम की डेमोस्ट्रैबिलिटी के बारे में सवाल स्टैकओवरफ्लो में या स्टैकएक्सचेंज में पोस्ट किया जाना चाहिए (यदि न तो, कहाँ है)?" यह मेटा स्टैकओवरफ़्लो के लिए एक प्रतीत होता है, है ना?
मत्तीस हूसलर

1
@MatiasHaeussler 1) C और C ++ अनिवार्य रूप से परमाणु चर, म्यूटेक्स और मल्टीथ्रेडिंग के "मेमोरी मॉडल" को साझा करते हैं। 2) इस पर प्रासंगिकता "मेमोरी मॉडल" होने के लाभों के बारे में है। मुझे लगता है कि मॉडल शून्य है क्योंकि लाभ शून्य है।
जिज्ञासु
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.