#Pragma omp समानांतर और #pragma omp समानांतर में अंतर
मैं नया 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];
}
}
इन दोनों के बीच क्या अंतर है?
जवाब
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 - 1
TOTAL_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];
}
}
आप तुरंत अंतर नोटिस करेंगे।
दूसरे मामले में, लूप को समानांतर नहीं किया जाता है। अर्थात्, पूरे लूप को प्रत्येक थ्रेड में निष्पादित किया जाता है । आम तौर पर, समानांतर क्षेत्र के अंदर जो कुछ भी होता है उसे सभी थ्रेड्स द्वारा निष्पादित किया जाता है।
आप अतिरिक्त रूप से पहले से मौजूद समानांतर क्षेत्र में लूप को इस प्रकार से समानांतर कर सकते हैं:
#pragma omp parallel
{
#pragma omp for
for (int i = 0; i < n; i++)
c[i] = a[i] + b[i];
}