#Pragma omp समानांतर और #pragma omp समानांतर में अंतर

Dec 11 2020

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

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

तथा

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

इन दोनों के बीच क्या अंतर है?

जवाब

5 dreamcrash Dec 11 2020 at 15:14

The

#pragma omp parallel:

की parallel regionएक टीम के साथ बनाएंगे threads, जहां प्रत्येक थ्रेड कोड के पूरे ब्लॉक को निष्पादित करेगा जो parallel regionएन्क्लोज करता है।

से OpenMP 5.1 एक अधिक औपचारिक विवरण पढ़ सकते हैं:

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

:

#pragma omp parallel for

एक parallel region(जैसा कि पहले बताया गया है) बनाएगा , और threadsउस क्षेत्र के लूप का पुनरावृत्तियों जो इसे संलग्न करता है, को असाइन किया जाएगा default chunk size, और default scheduleजो आम तौर पर है static । हालांकि, ध्यान रखें कि मानक के default scheduleविभिन्न ठोस कार्यान्वयन में भिन्न हो सकते हैं OpenMP

से OpenMP 5.1 यदि आप एक और अधिक औपचारिक विवरण पढ़ सकते हैं:

वर्शरिंग-लूप निर्माण यह निर्दिष्ट करता है कि एक या अधिक संबद्ध लूपों के पुनरावृत्तियों को उनके अंतर्निहित कार्यों के संदर्भ में टीम में थ्रेड्स के समानांतर निष्पादित किया जाएगा। पुनरावृत्तियों को थ्रेड्स में वितरित किया जाता है जो पहले से ही उस टीम में मौजूद हैं जो समानांतर क्षेत्र को निष्पादित कर रहा है जिसमें वर्किंग-लूप क्षेत्र याद दिलाता है

इसके अलावा ,

समानांतर लूप निर्माण एक समानांतर निर्माण को निर्दिष्ट करने के लिए एक शॉर्टकट है जिसमें एक या अधिक संबद्ध लूप के साथ लूप निर्माण है और कोई अन्य कथन नहीं है।

या अनौपचारिक रूप से, #pragma omp parallel forनिर्माता का एक संयोजन है #pragma omp parallelके साथ #pragma omp for। आपके मामले में, इसका मतलब यह होगा कि:

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

शब्दार्थ है, और तार्किक रूप से, समान है:

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

टीएल; डीआर: आपके उदाहरण में, #pragma omp parallel forलूप को थ्रेड्स के बीच समानांतर किया जाएगा ( यानी, लूप पुनरावृत्तियों को थ्रेड्स के बीच विभाजित किया जाएगा), जबकि #pragma omp parallel सभी थ्रेड्स के साथ (समानांतर में) सभी लूप पुनरावृत्तियों को निष्पादित करेंगे ।

4धागे के साथ इसे और अधिक उदाहरण के लिए #pragma omp parallel, कुछ इस तरह से परिणाम देगा:

जबकि और एक स्थिर के#pragma omp parallel for साथ कुछ इस तरह होगा:chunk_size=1 schedule

कोड-वार लूप तार्किक रूप से कुछ के समान रूपांतरित हो जाएगा :

for(int i=omp_get_thread_num(); i < n; i+=omp_get_num_threads())
{  
    c[i]=a[i]+b[i];
}

कहाँ omp_get_thread_num ()

Omp_get_thread_num दिनचर्या थ्रेड नंबर को, वर्तमान टीम के भीतर, कॉलिंग थ्रेड में लौटाता है।

और omp_get_num_threads ()

वर्तमान टीम में थ्रेड्स की संख्या लौटाता है। कार्यक्रम के अनुक्रमिक भाग में omp_get_num_threads 1 देता है।

या दूसरे शब्दों में, for(int i = THREAD_ID; i < n; i += TOTAL_THREADS)। समानांतर क्षेत्र पर बनाई गई टीम के थ्रेड्स की कुल संख्या THREAD_IDसे लेकर और तक का प्रतिनिधित्व 0करने के साथ ।TOTAL_THREADS - 1TOTAL_THREADS

मैंने सीखा है कि हमें लूप के लिए ओपनएमपी का उपयोग करते हुए #pragma omp को समानांतर रूप से उपयोग करने की आवश्यकता है। लेकिन मैंने भी #pragma omp समानांतर के साथ एक ही बात की कोशिश की है और यह मुझे सही आउटपुट भी दे रहा है।

यह आपको वही आउटपुट देता है, क्योंकि आपके कोड में:

 c[i]=a[i]+b[i];

सरणी aऔर सरणी bकेवल पढ़ी जाती हैं, और सरणी c[i]केवल एक ही अपडेट की जा रही है, और इसका मूल्य इस बात पर निर्भर नहीं करता है कि कितनी बार पुनरावृत्ति iनिष्पादित की जाएगी। फिर भी, #pragma omp parallel forप्रत्येक थ्रेड के साथ अपने आप को अपडेट करेगा i, जबकि #pragma omp parallelथ्रेड्स एक ही iएस को अपडेट करेंगे , इसलिए एक-दूसरे के मूल्यों को ओवरराइड करेंगे।

अब निम्नलिखित कोड के साथ भी ऐसा करने का प्रयास करें:

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

तथा

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

आप तुरंत अंतर नोटिस करेंगे।

2 DanielLangr Dec 11 2020 at 15:16

दूसरे मामले में, लूप को समानांतर नहीं किया जाता है। अर्थात्, पूरे लूप को प्रत्येक थ्रेड में निष्पादित किया जाता है । आम तौर पर, समानांतर क्षेत्र के अंदर जो कुछ भी होता है उसे सभी थ्रेड्स द्वारा निष्पादित किया जाता है।

आप अतिरिक्त रूप से पहले से मौजूद समानांतर क्षेत्र में लूप को इस प्रकार से समानांतर कर सकते हैं:

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