2011-06-11 14 views
9

पर प्रतीक्षा नहीं और कमी खंड मैं OpenMP का अध्ययन कर रहा हूँ, और निम्न उदाहरण भर में आया था:OpenMP: एक ही pragma

#pragma omp parallel shared(n,a,b,c,d,sum) private(i) 
{ 
    #pragma omp for nowait 
    for (i=0; i<n; i++) 
     a[i] += b[i]; 

    #pragma omp for nowait 
    for (i=0; i<n; i++) 
     c[i] += d[i]; 
    #pragma omp barrier 

    #pragma omp for nowait reduction(+:sum) 
    for (i=0; i<n; i++) 
     sum += a[i] + c[i]; 
} /*-- End of parallel region --*/ 

पाश के लिए पिछले में, वहाँ एक प्रतीक्षा नहीं है और एक कमी खंड है। क्या ये सही है? क्या कमी खंड को सिंक्रनाइज़ करने की आवश्यकता नहीं है?

+1

मुझे उत्सुकता है, आपको यह उदाहरण कहां मिला? –

+1

यह उदाहरण मेरे प्रोफेसर द्वारा दिया गया था। यह स्पष्ट बाधाओं के उपयोग की व्याख्या करने के लिए था, लेकिन मुझे यकीन नहीं है कि अंतिम लूप सही है या नहीं। – aperez

उत्तर

16

nowait एस दूसरे और अंतिम पाश में कुछ हद तक अनावश्यक हैं। OpenMP कल्पना क्षेत्र के अंत से पहले nowait का उल्लेख है तो शायद इस में रह सकते हैं।

लेकिन nowait दूसरा पाश से पहले, और स्पष्ट बाधा के बाद, बेमानी है।

और विशेष रूप से, reduction के लिए यह आवश्यक नहीं है।

इसके अलावा, shared और private खंड C++ आवश्यक नहीं हैं: shared निरर्थक है, और private नहीं किया जाना चाहिए। यदि आपको थ्रेड-प्राइवेट वैरिएबल की आवश्यकता है, तो इसे को समानांतर क्षेत्र के अंदर घोषित करें। विशेष रूप से, सी ++ में लूप वैरिएबल लूप के अंदर घोषित करना चाहिए, पहले नहीं।

#pragma omp parallel 
{ 
    #pragma omp for nowait 
    for (int i = 0; i < n; ++i) 
     a[i] += b[i]; 

    #pragma omp for 
    for (int i = 0; i < n; ++i) 
     c[i] += d[i]; 

    #pragma omp for nowait reduction(+:sum) 
    for (int i = 0; i < n; ++i) 
     sum += a[i] + c[i]; 
} // End of parallel region 
+0

हे @ कोनराड रुडॉल्फ क्या आप मेरे कोड को देख सकते हैं मुझे समझ में नहीं आता कि आप क्यों कहते हैं कि हमें साझा और निजी उपयोग करने की आवश्यकता नहीं है, मैं वीएस2012 – Gilad

2

OpenMP speficication का कहना है:

पाश निर्माण की वाक्य रचना इस प्रकार है:

#pragma omp for [clause[[,] clause] ... ] new-line 
    for-loops 

जहां खंड निम्नलिखित में से एक है:

... 
reduction(operator: list) 
... 
nowait 

तो वहाँ इस प्रकार अधिक खंड हो सकते हैं इस प्रकार दोनों कमी और अभी भी कथन हो सकते हैं।

reduction खंड में स्पष्ट तुल्यकालन की कोई जरूरत नहीं है - sum चर को जोड़ने reduction(+: sum) और पिछले बाधा बलों a और b की वजह से सिंक्रनाइज़ है reduction पाश के समय में अंतिम मान रही है। nowait का अर्थ है कि यदि थ्रेड लूप में काम खत्म करता है, तो उसे तब तक इंतजार नहीं करना पड़ेगा जब तक कि अन्य सभी थ्रेड एक ही लूप को पूरा नहीं कर लेते।

+0

आपके स्पष्टीकरण के लिए धन्यवाद। – aperez

8

कुछ संबंधों में यह होमवर्क समस्या की तरह लगता है, जिसे मैं लोगों के लिए नफरत करता हूं। दूसरी तरफ, ऊपर दिए गए उत्तर पूरी तरह से सटीक नहीं हैं और मुझे लगता है कि सही किया जाना चाहिए।

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

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

दूसरी तरफ, दूसरी लूप और स्पष्ट अवरोध पर अब भी की आवश्यकता नहीं हो सकती है। ओपनएमपी वी 3.0 विनिर्देश से पहले, कई लोगों ने माना कि कुछ सच था जिसे विनिर्देशन में स्पष्ट नहीं किया गया था।

स्थिर निर्धारित समय से एक शिकायत कार्यान्वयन सुनिश्चित करना चाहिए कि: OpenMP V3.0 विनिर्देश के साथ निम्नलिखित खंड 2.5.1 लूप का निर्माण, टेबल 2-1 अनुसूची खंड तरह मूल्यों, स्थिर (अनुसूची) को जोड़ा गया है उसी धागे के लिए तार्किक पुनरावृत्ति संख्याओं का असाइनमेंट दो लूप क्षेत्रों में उपयोग किया जाएगा यदि निम्न स्थितियां संतुष्ट हैं: 1) दोनों लूप क्षेत्रों में लूप पुनरावृत्तियों की एक ही संख्या है, 2) दोनों लूप क्षेत्रों में का एक ही मान है chunk_size निर्दिष्ट, या दोनों लूप क्षेत्रों में कोई chunk_size निर्दिष्ट नहीं है, और 3) दोनों लूप क्षेत्र समान समानांतर क्षेत्र से जुड़ते हैं। के बीच एक डेटा निर्भरता दो ऐसे लूपों में एक ही लॉजिकल पुनरावृत्तियों को संतुष्ट होने की गारंटी है अब प्रतीक्षा खंड के सुरक्षित उपयोग की अनुमति ( उदाहरणों के लिए पृष्ठ 170 पर अनुभाग ए.9 देखें)।

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

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

आप OpenMP V3.0 विनिर्देश को देखें, तो खंड 2.9.3.6 कमी खंड, तो आप पाएंगे निम्नलिखित:

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

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

+0

पर काम कर रहा हूं आपके बहुत विस्तृत उत्तर के लिए धन्यवाद ejd! मैं आपसे सहमत हूं कि यह वास्तव में होमवर्क प्रश्न की तरह प्रतीत होता है, क्योंकि यह मेरा कोड नहीं है - मैं उदाहरणों का अध्ययन करके ओपनएमपी सीखना शुरू कर रहा हूं। यदि आप इन प्रकार के प्रश्न पूछने के लिए एक उचित स्थान जानते हैं, या उन्हें प्रतिनिधित्व करने के लिए एक टैग (होमवर्क टैग के समान), तो कृपया मुझे बताएं। – aperez

+0

मुझे 'साझा'/'निजी' खंडों के उपयोग से असहमत होना है, और मैंने इसे अपने उत्तर में विस्तारित किया है: यदि आप निजी चर का उपयोग करते हैं, तो ** उन्हें निजी बनाएं **। प्रीप्रोकैसिंग क्लॉज पर भरोसा न करें, उन्हें स्थानीय दायरे में घोषित करें। सी ++ में ऐसा करने के लिए * नहीं * कारण है, और वास्तव में उपयोग के करीब चर घोषित करना * हमेशा * सी ++ में किया जाना चाहिए; इसके कारण, 'निजी' का उपयोग सी ++ में कोड गंध का स्पष्ट संकेत है। –

+3

कोनराड - चूंकि उदाहरण सी या सी ++ नहीं कहता है और सी 8 9 में आप जो भी दिखाया है वह नहीं कर सकते हैं, मुझे विश्वास है कि यह लाने के लिए मान्य है। जैसा कि मैंने कहा है, पिछले 12 वर्षों में ओपनएमपी में सबसे आम समस्या यह है कि उपयोगकर्ता समय-समय पर नहीं जाते हैं और देखें कि उनके कोड में चर का उपयोग कैसे किया जाता है। व्यक्तिगत रूप से मुझे लगता है कि डिफ़ॉल्ट को उपयोगकर्ता को यह बताने की आवश्यकता होनी चाहिए कि प्रत्येक चर का उपयोग कैसे किया जाए। यह निश्चित रूप से होने वाली समस्याओं की संख्या को कम करेगा। इस बीच, मैं लोगों को यह पता लगाने में मदद करने के लिए उपकरण पर काम करने के लिए वापस जाऊंगा कि उन्होंने क्या किया है। – ejd

संबंधित मुद्दे