2014-11-27 5 views
6

के लिए # ओएमपी को अलग करके ओवरहेड में शामिल करें मैं पुस्तक पढ़ रहा हूं पीटर एस पैचेको द्वारा समांतर प्रोग्रामिंग पर एक परिचय। धारा 5.6.2 में, इसने कांटा को कम करने/ओवरहेड में शामिल होने के बारे में एक दिलचस्प चर्चा की। अजीब भी स्थानांतरण तरह एल्गोरिथ्म पर विचार करें:ओपनएमपी फोर्क को घटाएं/# एमपी 3 समानांतर और

for(phase=0; phase < n; phase++){ 
    if(phase is even){ 
#  pragma omp parallel for default(none) shared(n) private(i) 
     for(i=1; i<n; i+=2){//meat} 
    } 
    else{ 
#  pragma omp parallel for default(none) shared(n) private(i) 
     for(i=1; i<n-1; i+=2){//meat} 
    } 
} 

लेखक का तर्क है ऊपर कोड कुछ हद तक उच्च कांटा है/भूमि के ऊपर में शामिल हो। क्योंकि धागे को फोर्क किया जाता है और बाहरी पाश के प्रत्येक पुनरावृत्ति में शामिल हो जाता है। इसलिए, वह निम्न संस्करण का प्रस्ताव: लेखकों के अनुसार

# pragma omp parallel default(none) shared(n) private(i, phase) 
for(phase=0; phase < n; phase++){ 
    if(phase is even){ 
#  pragma omp for 
     for(i=1; i<n; i+=2){//meat} 
    } 
    else{ 
#  pragma omp for 
     for(i=1; i<n-1; i+=2){//meat} 
    } 
} 

, दूसरे संस्करण कांटे बाहरी पाश शुरू होने से पहले धागे और प्रत्येक पुनरावृत्तियों के लिए धागे का पुन: उपयोग, बेहतर प्रदर्शन उपज।

हालांकि, मुझे दूसरे संस्करण की शुद्धता पर संदेह है। मेरी समझ में, #pragma omp parallel निर्देश थ्रेड के समूह को शुरू करता है और थ्रेड को समानांतर में निम्न संरचित ब्लॉक निष्पादित करने देता है। इस मामले में, संरचित ब्लॉक पूरे बाहरी फॉर-लूप for(phase=0 ...) होना चाहिए। तो, यह ऐसा मामला नहीं होना चाहिए जहां पूरे बाहरी पाश को चार धागे दिए जाने पर चार बार निष्पादित किया जाता है? यही है, अगर n=10, तो 40 पुनरावृत्तियों को 4 धागे पर निष्पादित किया जाएगा। मेरी समझ में क्या गलत है? और omp parallel (बिना के लिए) उपर्युक्त के लिए निम्न लूप के साथ कैसे खेलता है?

उत्तर

8

दूसरा संस्करण सही है।

प्रति OpenMP विनिर्देश, एक #pragma omp parallel for निर्देश सिर्फ #pragma omp parallel तुरंत #pragma omp for द्वारा पीछा के लिए एक शॉर्टकट है,

#pragma omp parallel 
{ 
    #pragma omp for 
    for(int i=0; i<N; ++i) { /*loop body*/ } 
} 

में के रूप में अगर वहाँ से पहले या पाश निर्माण के बाद समानांतर क्षेत्र में कुछ कोड है, यह क्षेत्र में प्रत्येक धागे द्वारा स्वतंत्र रूप से निष्पादित किया जाना चाहिए (जब तक कि अन्य ओपनएमपी निर्देशों तक सीमित न हो)। लेकिन, #pragma omp for एक कार्य साझाकरण है; उस निर्देश के बाद लूप क्षेत्र में सभी धागे द्वारा साझा किया गया है। अर्थात। इसे एक लूप के रूप में निष्पादित किया जाता है जिसे पुनरावृत्तियों को किसी भी तरह से धागे में विभाजित किया जाता है। इस प्रकार, यदि उपरोक्त समानांतर क्षेत्र को 4 धागे द्वारा निष्पादित किया जाता है, तो अभी भी लूप को केवल एक बार निष्पादित किया जाएगा, और 4 बार नहीं।

अपने प्रश्न में उदाहरण के लिए: चरण लूप प्रत्येक थ्रेड द्वारा व्यक्तिगत रूप से निष्पादित किया जाता है, लेकिन प्रत्येक चरण पुनरावृत्ति पर #pragma omp for साझा साझा लूप की शुरुआत दर्शाता है। एन = 10 के लिए, प्रत्येक थ्रेड एक साझा लूप 10 बार दर्ज करेगा, और इसके एक हिस्से को निष्पादित करेगा; तो आंतरिक लूप के 40 निष्पादन नहीं होंगे, लेकिन केवल 10.

नोट #pragma omp for के अंत में एक अंतर्निहित बाधा है; इसका मतलब यह है कि एक थ्रेड जो साझा लूप के अपने हिस्से को पूरा करता है, तब तक आगे नहीं बढ़ेगा जब तक कि अन्य सभी धागे भी अपने हिस्से को पूरा न करें। तो, निष्पादन धागे में सिंक्रनाइज़ किया जाता है। ज्यादातर मामलों में शुद्धता सुनिश्चित करना आवश्यक है; जैसे आपके उदाहरण में यह गारंटी देता है कि थ्रेड हमेशा एक ही चरण पर काम करते हैं। हालांकि यदि एक क्षेत्र के भीतर परिणामी साझा लूप एक साथ निष्पादित करने के लिए सुरक्षित हैं, तो nowait खंड का उपयोग अंतर्निहित बाधा को खत्म करने के लिए किया जा सकता है और थ्रेड तुरंत समांतर क्षेत्र में आगे बढ़ने की अनुमति देता है।

ध्यान दें कि कार्य साझा करने के निर्देशों की ऐसी प्रक्रिया ओपनएमपी के लिए काफी विशिष्ट है। अन्य समांतर प्रोग्रामिंग ढांचे के साथ, आप जिस तर्क का प्रयोग करते हैं वह सही हो सकता है।

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

+0

बहुत व्यापक उत्तर। – Neo1989

+0

मुझे संदेह है, जैसा कि आप बताते हैं कि दूसरा संस्करण अब और अधिक कुशल नहीं होगा। खासकर यदि 'एन >> nthreads'। –

+0

क्या आप मुझे बता सकते हैं कि कौन सा ओपनएमपी कार्यान्वयन "स्मार्ट" है ताकि प्रत्येक समांतर क्षेत्र के बाद धागे को फिर से शामिल न किया जा सके? – davide

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