क्या C ++ एक परमाणु के अंतर को पढ़ता और लिखता है?


81

मेरे पास दो सूत्र हैं, एक इंट को अद्यतन करना और एक इसे पढ़ना। यह एक आँकड़ा मूल्य है जहाँ पठन और लेखन का क्रम अप्रासंगिक है।

मेरा प्रश्न यह है कि क्या मुझे इस बहु-बाइट मूल्य तक पहुँच को सिंक्रनाइज़ करने की आवश्यकता है? या, एक और तरीका रखो, क्या लेखन का हिस्सा पूरा हो सकता है और बाधित हो सकता है, और फिर पढ़ा होता है।

उदाहरण के लिए, एक मान के बारे में सोचें = 0x0000FFFF जो 0x00010000 के बढ़े हुए मूल्य को प्राप्त करता है।

क्या कोई ऐसा समय है जहां मान 0x0001FFFF जैसा दिखता है, जिसके बारे में मुझे चिंतित होना चाहिए? निश्चित रूप से यह जितना बड़ा होगा, उतना ही संभव होगा।

मैंने हमेशा इस प्रकार के एक्सेस को सिंक्रनाइज़ किया है, लेकिन उत्सुक था कि समुदाय क्या सोचता है।


5
वास्तव में? मुझे परवाह नहीं है कि समुदाय ने क्या सोचा है। मुझे परवाह है कि क्या तथ्य हैं :)
seep

1
दिलचस्प विषय पर पढ़ें: channel9.msdn.com/Shows/Going+Deep/…
ereOn

इसके लिए विशेष रूप से =: stackoverflow.com/questions/8290768/…
Ciro Santilli 郝海东 stack stack stack

जवाबों:


47

पहले तो यह सोच सकते हैं कि देशी मशीन के आकार को पढ़ना और लिखना परमाणु है लेकिन प्रोसेसर / कोर के बीच कैश सुसंगतता से निपटने के लिए कई समस्याएं हैं। विंडोज पर परमाणु संचालन जैसे * विंडोज पर और लिनक्स पर बराबर का उपयोग करें। C ++ 0x में एक अच्छा और क्रॉस-प्लेटफ़ॉर्म इंटरफ़ेस में इन्हें लपेटने के लिए "परमाणु" टेम्पलेट होगा। अभी के लिए यदि आप एक मंच अमूर्त परत का उपयोग कर रहे हैं तो यह इन कार्यों को प्रदान कर सकता है। ACE करता है, वर्ग टेम्पलेट देखें ACE_Atomic_Op


ACE_Atomic_Op का दस्तावेज़ स्थानांतरित हो गया है - यह अब dre.vanderbilt.edu/~schmidt/DOC_ROOT/ACE/ace/Atomic_Op.inl
बायरन

63

लड़का, क्या सवाल। जिसका उत्तर है:

हाँ, नहीं, हम्मम, ठीक है, यह निर्भर करता है

यह सब सिस्टम की वास्तुकला के लिए नीचे आता है। IA32 पर एक सही ढंग से संरेखित पता एक परमाणु ऑपरेशन होगा। अनलग्ड राइट परमाणु हो सकता है, यह उपयोग में कैशिंग सिस्टम पर निर्भर करता है। यदि मेमोरी एक एल 1 कैश लाइन के भीतर है तो यह परमाणु है, अन्यथा यह नहीं है। सीपीयू और रैम के बीच बस की चौड़ाई परमाणु प्रकृति को प्रभावित कर सकती है: 8086 पर एक सही ढंग से संरेखित 16bit लिखी गई परमाणु थी, जबकि 8088 में एक ही लेखन नहीं था क्योंकि 8088 में केवल 8 बिट बस थी जबकि 8086 में एक थी 16 बिट बस।

इसके अलावा, यदि आप C / C ++ का उपयोग कर रहे हैं, तो साझा मूल्य को अस्थिरता के रूप में चिह्नित करना न भूलें, अन्यथा ऑप्टिमाइज़र को लगता है कि चर आपके थ्रेड्स में से किसी में अद्यतन नहीं है।


23
वाष्पशील खोजशब्द बहुस्तरीय कार्यक्रमों में उपयोगी नहीं है stackoverflow.com/questions/2484980/…

5
@IngeHenriksen: मैं उस लिंक से आश्वस्त नहीं हूं।
Skizz

एक अन्य स्रोत, लेकिन दुर्भाग्य से बहुत पुराना (यह std :: atomic से पहले) है: web.archive.org/web/20190219170904/https://software.intel.com/…
मैक्स बर्राक्लो

11

यदि आप 4-बाइट मान पढ़ / लिख रहे हैं और यह DWORD- मेमोरी में संरेखित है और आप I32 आर्किटेक्चर पर चल रहे हैं, तो पढ़ता है और लिखता है कि परमाणु हैं।


2
इंटेल आर्किटेक्चर सॉफ्टवेयर डेवलपर के मैनुअल में यह कहां कहा गया है?
डैनियल ट्रेबिएन

2
@DanielTrebbien: शायद stackoverflow.com/questions/5002046/…
sehe

9

हां, आपको एक्सेस को सिंक्रनाइज़ करने की आवश्यकता है। C ++ 0x में यह डेटा रेस और अपरिभाषित व्यवहार होगा। POSIX थ्रेड्स के साथ यह पहले से ही अपरिभाषित व्यवहार है।

व्यवहार में, यदि डेटा प्रकार मूल शब्द आकार से बड़ा है, तो आपको खराब मान मिल सकता है। इसके अलावा, एक और धागा कभी नहीं पढ़ा और / या लिखने के अनुकूलन के कारण लिखे गए मूल्य को देख सकता है।


3

आपको सिंक्रनाइज़ करना होगा, लेकिन कुछ आर्किटेक्चर पर इसे करने के कुशल तरीके हैं।

सबसे अच्छा है सबरूटीन्स (शायद मैक्रोज़ के पीछे नकाबपोश) का उपयोग करें ताकि आप सशर्त रूप से प्लेटफ़ॉर्म-विशिष्ट लोगों के साथ कार्यान्वयन को बदल सकें।

लिनक्स कर्नेल में पहले से ही कुछ कोड हैं।



2

यह कहने के लिए कि हर किसी ने ऊपर कहा, भाषा प्री-सी ++ 0x कई थ्रेड से साझा मेमोरी एक्सेस के बारे में कुछ भी गारंटी नहीं दे सकती है। कोई भी गारंटी संकलक तक होगी।


0

नहीं, वे नहीं हैं (या कम से कम आप यह नहीं मान सकते कि वे हैं)। यह कहने के बाद कि, परमाणु रूप से ऐसा करने के लिए कुछ तरकीबें हैं, लेकिन वे आमतौर पर पोर्टेबल नहीं हैं (देखें तुलना-और-अदला-बदली )।


0

मैं कई और विशेष रूप से जेसन से सहमत हूं । खिड़कियों पर, संभवतः इंटरलॉकड और उसके दोस्तों का उपयोग करेगा।


0

ऊपर उल्लिखित कैश समस्या से अलग ...

यदि आप एक छोटे रजिस्टर आकार के साथ प्रोसेसर को कोड पोर्ट करते हैं तो यह अब परमाणु नहीं होगा।

IMO, थ्रेडिंग मुद्दे भी इसे जोखिम में डालने के लिए कांटेदार हैं।


0

एकमात्र पोर्टेबल तरीका यह है कि अपने कंपाइलर के लिए सिग्नल.एच हेडर में परिभाषित sig_atomic_t टाइप का उपयोग करें। अधिकांश C और C ++ कार्यान्वयन में, यह एक int है। फिर अपने चर को "अस्थिर sig_atomic_t" घोषित करें।


अस्थिर वह नहीं करता है जो आपको लगता है कि यह stackoverflow.com/questions/2484980/…
सैम मिलर

0

इसका उदाहरण दें

int x;
x++;
x=x+5;

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

एक और उदाहरण,

x=5;

फिर से, आपको यह देखने के लिए कोड को अलग करना होगा कि यहां वास्तव में क्या होता है।


2
लेकिन कंपाइलर इसमें ऑप्टिमाइज़ कर सकता था x+=6
टीसी

0

टीसी, मुझे लगता है कि आप एक निरंतर (जैसे 6) का उपयोग करते हैं, निर्देश एक मशीन चक्र में पूरा नहीं होगा। X ++ की तुलना में x + = 6 के निर्देश सेट को देखने का प्रयास करें


0

कुछ लोग सोचते हैं कि ++ सी परमाणु है, लेकिन उत्पन्न विधानसभा पर नजर है। उदाहरण के लिए 'gcc -S' के साथ:

movl    cpt.1586(%rip), %eax
addl    $1, %eax
movl    %eax, cpt.1586(%rip)

इंट को बढ़ाने के लिए, संकलक पहले इसे एक रजिस्टर में लोड करता है, और इसे मेमोरी में वापस स्टोर करता है। यह परमाणु नहीं है।


1
यह कोई समस्या नहीं है यदि केवल एक धागा चर को लिख रहा है, क्योंकि कोई फाड़ नहीं है।
बेन वोइग्ट

0

निश्चित रूप से नहीं! हमारे उच्चतम सी ++ प्राधिकरण, एम। बूस्ट:
"साधारण" चर पर संचालन परमाणु होने की गारंटी नहीं है।


2
उस लिंक केवल कहते arithmeticआपरेशन 'आम' चर पर एक रीड-अद्यतन-लिखने अनुक्रम के होते हैं जो परमाणु नहीं होते हैं, चाहे नहीं readया write'आम' चर पर आपरेशन परमाणु या नहीं कर रहे हैं।
D3Hunter
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.