ओपनएमपी में परमाणु और महत्वपूर्ण के बीच अंतर क्या है?
मे यह कर सकती हु
#pragma omp atomic
g_qCount++;
लेकिन ऐसा नहीं है
#pragma omp critical
g_qCount++;
?
ओपनएमपी में परमाणु और महत्वपूर्ण के बीच अंतर क्या है?
मे यह कर सकती हु
#pragma omp atomic
g_qCount++;
लेकिन ऐसा नहीं है
#pragma omp critical
g_qCount++;
?
जवाबों:
G_qCount पर प्रभाव समान है, लेकिन जो किया जाता है वह अलग है।
एक ओपनएमपी महत्वपूर्ण खंड पूरी तरह से सामान्य है - यह कोड के किसी भी मनमाने ढंग से ब्लॉक को घेर सकता है। आप उस सामान्यता के लिए भुगतान करते हैं, हालांकि, महत्वपूर्ण ओवरहेड को हर बार एक थ्रेड में प्रवेश करने और महत्वपूर्ण खंड (क्रमांकन की अंतर्निहित लागत के शीर्ष पर) से बाहर निकलता है।
(इसके अलावा, ओपनएमपी में सभी अनाम महत्वपूर्ण खंडों को समान माना जाता है (यदि आप चाहें, तो सभी अनाम महत्वपूर्ण अनुभागों के लिए केवल एक लॉक है), ताकि यदि एक धागा ऊपर के रूप में एक [अनाम] महत्वपूर्ण खंड में हो, तो कोई भी धागा दर्ज नहीं किया जा सकता है [अनाम] महत्वपूर्ण अनुभाग। जैसा कि आप अनुमान लगा सकते हैं, आप महत्वपूर्ण अनुभागों का उपयोग करके इसके चारों ओर प्राप्त कर सकते हैं)।
एक परमाणु ऑपरेशन में बहुत कम ओवरहेड होता है। जहां उपलब्ध है, यह एक परमाणु वेतन वृद्धि ऑपरेशन (प्रदान) हार्डवेयर पर लाभ उठाता है; उस स्थिति में कोड की लाइन में प्रवेश करने / बाहर निकलने पर लॉक / अनलॉक की आवश्यकता नहीं है, यह सिर्फ परमाणु वृद्धि करता है जिसे हार्डवेयर बताता है कि आपके साथ हस्तक्षेप नहीं किया जा सकता है।
अपसाइड यह है कि ओवरहेड बहुत कम है, और एक परमाणु ऑपरेशन में एक धागा होने के बारे में किसी भी (अलग) परमाणु संचालन को ब्लॉक नहीं करता है। डाउनसाइड ऑपरेशन का प्रतिबंधित सेट है जो परमाणु समर्थन करता है।
बेशक, किसी भी मामले में, आप क्रमांकन की लागत को लागू करते हैं।
महत्वपूर्ण अनुभाग:
"नाम" टैग के उचित उपयोग के साथ ब्लॉकों के क्रमबद्ध समूहों तक बढ़ाया जा सकता है।
और धीमा!
परमाणु संचालन:
बहुत तेज है!
केवल एक विशेष ऑपरेशन के क्रमांकन को सुनिश्चित करता है।
सबसे तेज़ तरीका न तो महत्वपूर्ण है और न ही परमाणु। लगभग, महत्वपूर्ण खंड के अलावा साधारण जोड़ की तुलना में 200 गुना अधिक महंगा है, परमाणु जोड़ 25 गुना अधिक महंगा है और फिर साधारण जोड़ है।
सबसे तेज़ विकल्प (हमेशा लागू नहीं) प्रत्येक थ्रेड को अपना काउंटर देना है और कुल योग की आवश्यकता होने पर ऑपरेशन को कम करना है।
की सीमाएं atomic
महत्वपूर्ण हैं। उन्हें ओपनएमपी चश्मा पर विस्तृत होना चाहिए । MSDN एक त्वरित धोखा पत्र प्रदान करता है क्योंकि मुझे आश्चर्य नहीं होगा अगर यह नहीं बदलेगा। (विजुअल स्टूडियो 2012 में मार्च 2002 से एक ओपनएमपी कार्यान्वयन है।) MSDN को उद्धृत करने के लिए:
अभिव्यक्ति कथन में निम्न में से एक रूप होना चाहिए:
x
बिनोप =expr
x++
++x
x--
--x
पूर्ववर्ती अभिव्यक्तियों में: अदिश प्रकार के साथ
x
एकlvalue
अभिव्यक्ति है।expr
स्केलर प्रकार के साथ एक अभिव्यक्ति है, और यह द्वारा निर्दिष्ट वस्तु का संदर्भ नहीं देता हैx
। binop एक ओवरलोड ऑपरेटर नहीं है और में से एक है+
,*
,-
,/
,&
,^
,|
,<<
, या>>
।
मैं atomic
तब उपयोग करने की सलाह देता हूं जब आप अन्यथा महत्वपूर्ण वर्गों को नाम दे सकते हैं। उनका नामकरण करना महत्वपूर्ण है; आप इस तरह से सिरदर्द से बचेंगे।
पहले से ही यहाँ महान स्पष्टीकरण। हालांकि, हम थोड़ा गहरा गोता लगा सकते हैं। ओपनएमपी में परमाणु और महत्वपूर्ण खंड अवधारणाओं के बीच मुख्य अंतर को समझने के लिए , हमें पहले लॉक की अवधारणा को समझना होगा । आइए समीक्षा करें कि हमें ताले का उपयोग करने की आवश्यकता क्यों है ।
एक समानांतर प्रोग्राम को कई थ्रेड द्वारा निष्पादित किया जा रहा है। निर्धारक परिणाम तभी होंगे जब हम इन थ्रेड्स के बीच सिंक्रनाइज़ेशन करेंगे । बेशक, थ्रेड्स के बीच सिंक्रनाइज़ेशन की हमेशा आवश्यकता नहीं होती है। हम उन मामलों का उल्लेख कर रहे हैं जो सिंक्रनाइज़ेशन आवश्यक हैं।
बहु-थ्रेडेड प्रोग्राम में थ्रेड्स को सिंक्रनाइज़ करने के लिए , हम लॉक का उपयोग करेंगे । जब एक समय में केवल एक थ्रेड द्वारा पहुंच को प्रतिबंधित करना आवश्यक होता है, तो लॉक एस प्ले में आते हैं। ताला अवधारणा कार्यान्वयन प्रोसेसर से प्रोसेसर को बदल सकता है। आइए जानें कि एक एल्गोरिदम बिंदु से एक साधारण लॉक कैसे काम कर सकता है।
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, इत्यादि) करना चाहते हैं और परमाणु निर्देश का उपयोग करने की अनुशंसा की जाती है ।महत्वपूर्ण निर्देश जब गहन खंड द्वारा अधिक कम्प्यूटेशनल रूप से जटिल क्षेत्र किया जा रहा है।
जब आप केवल एक ही निर्देश के लिए पारस्परिक बहिष्करण को सक्षम करने की आवश्यकता होती है, तो परमाणु अपेक्षाकृत प्रदर्शन कुशल होता है, लेकिन यह महत्वपूर्ण नहीं है।
एटॉमिक एक स्टेटमेंट क्रिटिकल सेक्शन है, यानी आप एक स्टेटमेंट एक्जीक्यूशन के लिए लॉक होते हैं
महत्वपूर्ण खंड कोड के एक ब्लॉक पर एक ताला है
एक अच्छा कंपाइलर आपके दूसरे कोड को उसी तरह ट्रांसलेट करेगा जैसे वह पहले करता है
++
और*=
) और है कि अगर वे हार्डवेयर में समर्थित नहीं हैं, वे द्वारा प्रतिस्थापित किया जा सकता हैcritical
वर्गों।