ओपनएमपी में परमाणु और महत्वपूर्ण के बीच अंतर क्या है?


111

ओपनएमपी में परमाणु और महत्वपूर्ण के बीच अंतर क्या है?

मे यह कर सकती हु

#pragma omp atomic
g_qCount++;

लेकिन ऐसा नहीं है

#pragma omp critical
g_qCount++;

?

जवाबों:


173

G_qCount पर प्रभाव समान है, लेकिन जो किया जाता है वह अलग है।

एक ओपनएमपी महत्वपूर्ण खंड पूरी तरह से सामान्य है - यह कोड के किसी भी मनमाने ढंग से ब्लॉक को घेर सकता है। आप उस सामान्यता के लिए भुगतान करते हैं, हालांकि, महत्वपूर्ण ओवरहेड को हर बार एक थ्रेड में प्रवेश करने और महत्वपूर्ण खंड (क्रमांकन की अंतर्निहित लागत के शीर्ष पर) से बाहर निकलता है।

(इसके अलावा, ओपनएमपी में सभी अनाम महत्वपूर्ण खंडों को समान माना जाता है (यदि आप चाहें, तो सभी अनाम महत्वपूर्ण अनुभागों के लिए केवल एक लॉक है), ताकि यदि एक धागा ऊपर के रूप में एक [अनाम] महत्वपूर्ण खंड में हो, तो कोई भी धागा दर्ज नहीं किया जा सकता है [अनाम] महत्वपूर्ण अनुभाग। जैसा कि आप अनुमान लगा सकते हैं, आप महत्वपूर्ण अनुभागों का उपयोग करके इसके चारों ओर प्राप्त कर सकते हैं)।

एक परमाणु ऑपरेशन में बहुत कम ओवरहेड होता है। जहां उपलब्ध है, यह एक परमाणु वेतन वृद्धि ऑपरेशन (प्रदान) हार्डवेयर पर लाभ उठाता है; उस स्थिति में कोड की लाइन में प्रवेश करने / बाहर निकलने पर लॉक / अनलॉक की आवश्यकता नहीं है, यह सिर्फ परमाणु वृद्धि करता है जिसे हार्डवेयर बताता है कि आपके साथ हस्तक्षेप नहीं किया जा सकता है।

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

बेशक, किसी भी मामले में, आप क्रमांकन की लागत को लागू करते हैं।


5
"आप पोर्टेबिलिटी को ढीला कर सकते हैं" - मुझे यकीन नहीं है कि यह सच है। मानक (संस्करण 2.0) निर्दिष्ट करता है जो परमाणु संचालन की अनुमति है (मूल रूप से तरह बातें ++और *=) और है कि अगर वे हार्डवेयर में समर्थित नहीं हैं, वे द्वारा प्रतिस्थापित किया जा सकता है criticalवर्गों।
दान आर

@DanRoche: हाँ, आप काफी सही हैं। मुझे नहीं लगता कि यह कथन कभी सही था, अब मैं इसे सही करूंगा।
जोनाथन डर्सी

कुछ दिनों पहले मैंने एक OpenMP ट्यूटोरियल का अनुसरण किया था, और जहाँ तक मैंने समझा, दो अलग-अलग कोड में अंतर है। यह परिणाम भिन्न हो सकता है क्योंकि महत्वपूर्ण खंड आश्वासन देता है कि निर्देश थ्रेड द्वारा निष्पादित होता है, हालांकि यह संभव है कि निर्देश: g_qCount = g_qCount + 1; थ्रेड 1 के लिए बस g_qCount परिणाम को केवल मेमोरी मेमोरी में नहीं राइटबफ़र में संग्रहीत करता है, और जब थ्रेड 2 मान g_qCount प्राप्त करते हैं, तो यह केवल RAM में पढ़ता है, राइटबफ़र में नहीं। परमाणु निर्देश ने निर्देश दिया कि स्मृति में डेटा
प्रवाहित हो गया

31

ओपनएमपी में, सभी अनाम महत्वपूर्ण अनुभाग परस्पर अनन्य हैं।

महत्वपूर्ण और परमाणु के बीच सबसे महत्वपूर्ण अंतर यह है कि परमाणु केवल एक असाइनमेंट की रक्षा कर सकता है और आप इसे विशिष्ट ऑपरेटरों के साथ उपयोग कर सकते हैं।


13
यह पिछले उत्तर की टिप्पणी (या संपादित) बेहतर होता।
कियान

20

महत्वपूर्ण अनुभाग:

  • कोड के ब्लॉक का क्रमांकन सुनिश्चित करता है।
  • "नाम" टैग के उचित उपयोग के साथ ब्लॉकों के क्रमबद्ध समूहों तक बढ़ाया जा सकता है।

  • और धीमा!

परमाणु संचालन:

  • बहुत तेज है!

  • केवल एक विशेष ऑपरेशन के क्रमांकन को सुनिश्चित करता है।


9
लेकिन यह उत्तर बहुत पठनीय है और पहले उत्तर का एक बड़ा योग होगा
मिशैल मिस्ज़कज़ीज़िन

7

सबसे तेज़ तरीका न तो महत्वपूर्ण है और न ही परमाणु। लगभग, महत्वपूर्ण खंड के अलावा साधारण जोड़ की तुलना में 200 गुना अधिक महंगा है, परमाणु जोड़ 25 गुना अधिक महंगा है और फिर साधारण जोड़ है।

सबसे तेज़ विकल्प (हमेशा लागू नहीं) प्रत्येक थ्रेड को अपना काउंटर देना है और कुल योग की आवश्यकता होने पर ऑपरेशन को कम करना है।


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

6

की सीमाएं atomicमहत्वपूर्ण हैं। उन्हें ओपनएमपी चश्मा पर विस्तृत होना चाहिए । MSDN एक त्वरित धोखा पत्र प्रदान करता है क्योंकि मुझे आश्चर्य नहीं होगा अगर यह नहीं बदलेगा। (विजुअल स्टूडियो 2012 में मार्च 2002 से एक ओपनएमपी कार्यान्वयन है।) MSDN को उद्धृत करने के लिए:

अभिव्यक्ति कथन में निम्न में से एक रूप होना चाहिए:

xबिनोप =expr

x++

++x

x--

--x

पूर्ववर्ती अभिव्यक्तियों में: अदिश प्रकार के साथ xएक lvalueअभिव्यक्ति है। exprस्केलर प्रकार के साथ एक अभिव्यक्ति है, और यह द्वारा निर्दिष्ट वस्तु का संदर्भ नहीं देता है xbinop एक ओवरलोड ऑपरेटर नहीं है और में से एक है +, *, -, /, &, ^, |, <<, या >>

मैं atomicतब उपयोग करने की सलाह देता हूं जब आप अन्यथा महत्वपूर्ण वर्गों को नाम दे सकते हैं। उनका नामकरण करना महत्वपूर्ण है; आप इस तरह से सिरदर्द से बचेंगे।


1
यह सब नहीं है, हमारे पास अन्य उन्नत परमाणु निर्देश हैं जैसे: #pragma omp सुगन्धित अपडेट (या पढ़ें, अपटेट, राइट, कैप्चर) तो यह हमें कुछ अन्य लाभकारी स्टेटमेंट
घटिया

1

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

एक समानांतर प्रोग्राम को कई थ्रेड द्वारा निष्पादित किया जा रहा है। निर्धारक परिणाम तभी होंगे जब हम इन थ्रेड्स के बीच सिंक्रनाइज़ेशन करेंगे । बेशक, थ्रेड्स के बीच सिंक्रनाइज़ेशन की हमेशा आवश्यकता नहीं होती है। हम उन मामलों का उल्लेख कर रहे हैं जो सिंक्रनाइज़ेशन आवश्यक हैं।

बहु-थ्रेडेड प्रोग्राम में थ्रेड्स को सिंक्रनाइज़ करने के लिए , हम लॉक का उपयोग करेंगे । जब एक समय में केवल एक थ्रेड द्वारा पहुंच को प्रतिबंधित करना आवश्यक होता है, तो लॉक एस प्ले में आते हैं। ताला अवधारणा कार्यान्वयन प्रोसेसर से प्रोसेसर को बदल सकता है। आइए जानें कि एक एल्गोरिदम बिंदु से एक साधारण लॉक कैसे काम कर सकता है।

1. Define a variable called lock.
2. For each thread:
   2.1. Read the lock.
   2.2. If lock == 0, lock = 1 and goto 3    // Try to grab the lock
       Else goto 2.1    // Wait until the lock is released
3. Do something...
4. lock = 0    // Release the lock

दिए गए एल्गोरिथ्म को हार्डवेयर भाषा में निम्नानुसार लागू किया जा सकता है। हम एक एकल प्रोसेसर मानेंगे और उस में ताले के व्यवहार का विश्लेषण करेंगे। इस अभ्यास के लिए, आइए निम्न में से किसी एक प्रोसेसर को मानें : MIPS , अल्फा , ARM या पावर

try:    LW R1, lock
        BNEZ R1, try
        ADDI R1, R1, #1
        SW R1, lock

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

1. Define a variable called lock.
2. For each thread:
   2.1. Read the lock and put the address of lock variable inside the Link Register.
   2.2. If (lock == 0) and (&lock == Link Register), lock = 1 and reset the Link Register then goto 3    // Try to grab the lock
       Else goto 2.1    // Wait until the lock is released
3. Do something...
4. lock = 0    // Release the lock

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

महत्वपूर्ण और परमाणु के बीच मुख्य अंतर इस विचार से आता है कि:

ताले (एक नया चर) का उपयोग क्यों करें जबकि हम वास्तविक चर (जो हम उस पर एक ऑपरेशन कर रहे हैं) का उपयोग कर सकते हैं, ताला चर के रूप में?

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


-5

जब आप केवल एक ही निर्देश के लिए पारस्परिक बहिष्करण को सक्षम करने की आवश्यकता होती है, तो परमाणु अपेक्षाकृत प्रदर्शन कुशल होता है, लेकिन यह महत्वपूर्ण नहीं है।


13
यह स्पष्टीकरण के बिना स्वीकृत जवाब के खराब-शब्द वाले प्रतिबंध से ज्यादा कुछ नहीं है।
उच्च प्रदर्शन मार्क

-5

एटॉमिक एक स्टेटमेंट क्रिटिकल सेक्शन है, यानी आप एक स्टेटमेंट एक्जीक्यूशन के लिए लॉक होते हैं

महत्वपूर्ण खंड कोड के एक ब्लॉक पर एक ताला है

एक अच्छा कंपाइलर आपके दूसरे कोड को उसी तरह ट्रांसलेट करेगा जैसे वह पहले करता है


यह सिर्फ गलत है। कृपया उस सामान के बारे में बात न करें जिसे आप नहीं समझते हैं।
jcsahnwaldt
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.