openmp
OpenMP में लूप समानता
खोज…
पैरामीटर
धारा | पैरामीटर |
---|---|
private | कोमा-अलग-अलग निजी चर की सूची |
firstprivate | private तरह, लेकिन लूप में प्रवेश करने से पहले वैरिएबल के मान से आरंभिक |
lastprivate | private तरह, लेकिन चर को निकलने पर लूप के अंतिम पुनरावृत्ति के अनुरूप मूल्य मिलेगा |
reduction | कमी ऑपरेटर : कॉमा से अलग-अलग कटौती चर की सूची |
schedule | 3 पूर्व के लिए कोमा के बाद एक वैकल्पिक चंक आकार के साथ static , dynamic , guided , auto या runtime |
collapse | पूरी तरह से नेस्टेड छोरों की संख्या एक साथ गिरने और समानांतर करने के लिए |
ordered | बताता है कि लूप के कुछ हिस्सों को इन-क्रम में रखना होगा (इन भागों को विशेष रूप से लूप बॉडी के अंदर कुछ ordered क्लॉज़ से पहचाना जाएगा) |
nowait | लूप निर्माण के अंत में डिफ़ॉल्ट रूप से मौजूद अंतर्निहित अवरोध को हटा दें |
टिप्पणियों
schedule
खंड का अर्थ इस प्रकार है:
-
static[,chunk]
: स्टैटिकली राउंड-रॉबिन फैशन मेंchunk
साइज़ के बैच में लूप पुनरावृत्तियों को सांख्यिकीय रूप से वितरित करें (जिसका अर्थ है कि वितरण लूप में प्रवेश करने से पहले किया जाता है)। यदिchunk
निर्दिष्ट नहीं किया गया है, तो विखंडू जितना संभव हो उतना संभव है और उनमें से प्रत्येक पर एक धागा मिलता है। -
dynamic[,chunk]
: पहले-आओ-पहले पाओ की नीति के साथchunk
आकार के बैचों द्वारा थ्रेड्स के बीच लूप पुनरावृत्तियों को वितरित करें, जब तक कोई बैच नहीं रहता। यदि निर्दिष्ट नहीं है, तोchunk
1 पर सेट है -
guided[,chunk]
:dynamic
तरह लेकिन बैचों के साथ जो आकार छोटे और छोटे होते हैं, 1 से नीचे -
auto
: कंपाइलर और / या रन टाइम लाइब्रेरी तय करें कि सबसे उपयुक्त क्या है -
runtime
:OMP_SCHEDULE
पर्यावरण चर केOMP_SCHEDULE
से चलाने के समय पर निर्णय कीOMP_SCHEDULE
करें। यदि रन टाइम पर पर्यावरण चर को परिभाषित नहीं किया जाता है, तो डिफ़ॉल्ट शेड्यूलिंग का उपयोग किया जाएगा
schedule
लिए डिफ़ॉल्ट कार्यान्वयन परिभाषित है । कई वातावरणों पर यह static
, लेकिन dynamic
भी हो सकता है या बहुत अच्छी तरह से auto
हो सकता है। इसलिए, सावधान रहें कि आपका कार्यान्वयन स्पष्ट रूप से इसे निर्धारित किए बिना उस पर निर्भर नहीं है।
उपरोक्त उदाहरणों में, हमने फ़्यूज़ किए गए फॉर्म का उपयोग parallel for
या parallel do
। हालांकि, लूप निर्माण का उपयोग parallel
निर्देश के साथ फ्यूज करने के बिना किया जा सकता है, #pragma omp for [...]
या #pragma omp for [...]
!$omp do [...]
के लिए एक parallel
क्षेत्र के भीतर स्वसंपूर्ण निर्देश के रूप में।
केवल फोरट्रान संस्करण के लिए, लंबित लूप (ओं) के लूप इंडेक्स वेरिएबल (एस) हमेशा डिफ़ॉल्ट रूप से private
होते हैं। इसलिए स्पष्ट रूप से उन्हें private
घोषित करने की कोई आवश्यकता नहीं है (हालांकि ऐसा करना कोई त्रुटि नहीं है)।
सी और सी ++ संस्करण के लिए, लूप इंडेक्स किसी भी अन्य चर की तरह हैं। इसलिए, यदि उनका दायरा समांतर लूप (ओं) के बाहर फैला हुआ है (जिसका अर्थ है कि यदि उन्हें for ( int i = ...)
तरह घोषित नहीं किया गया है, बल्कि int i; ... for ( i = ... )
तो वे private
घोषित किया जाना है।
C में विशिष्ट उदाहरण
#include <stdio.h>
#include <math.h>
#include <omp.h>
#define N 1000000
int main() {
double sum = 0;
double tbegin = omp_get_wtime();
#pragma omp parallel for reduction( +: sum )
for ( int i = 0; i < N; i++ ) {
sum += cos( i );
}
double wtime = omp_get_wtime() - tbegin;
printf( "Computing %d cosines and summing them with %d threads took %fs\n",
N, omp_get_max_threads(), wtime );
return sum;
}
इस उदाहरण में, हम केवल 1 मिलियन कोसाइन की गणना करते हैं और समानांतर में उनके मानों को जोड़ते हैं। हम यह भी देखते हैं कि समानांतर का प्रदर्शन पर कोई प्रभाव पड़ता है या नहीं। अंत में, चूंकि हम समय को मापते हैं, इसलिए हमें यह सुनिश्चित करना होगा कि कंपाइलर हमारे द्वारा किए गए कार्य का अनुकूलन नहीं करेगा, इसलिए हम इसे वापस करके परिणाम का उपयोग करने का दिखावा करते हैं।
फोरट्रान में एक ही उदाहरण
program typical_loop
use omp_lib
implicit none
integer, parameter :: N = 1000000, kd = kind( 1.d0 )
real( kind = kd ) :: sum, tbegin, wtime
integer :: i
sum = 0
tbegin = omp_get_wtime()
!$omp parallel do reduction( +: sum )
do i = 1, N
sum = sum + cos( 1.d0 * i )
end do
!$omp end parallel do
wtime = omp_get_wtime() - tbegin
print "( 'Computing ', i7, ' cosines and summing them with ', i2, &
& ' threads took ', f6.4,'s' )", N, omp_get_max_threads(), wtime
if ( sum > N ) then
print *, "we only pretend using sum"
end if
end program typical_loop
यहाँ फिर से हम 1 मिलियन कोसाइन की गणना और संचय करते हैं। हमारे पास लूप का समय है और अवांछित संकलक अनुकूलन-से बचने के लिए, हम परिणाम का उपयोग करने का दिखावा करते हैं।
उदाहरणों को संकलित करना और चलाना
GCC संस्करण 4.4 का उपयोग कर 8 कोर लिनक्स मशीन पर, C कोड को संकलित किया जा सकता है और निम्नलिखित तरीके से चलाया जा सकता है:
$ gcc -std=c99 -O3 -fopenmp loop.c -o loopc -lm
$ OMP_NUM_THREADS=1 ./loopc
Computing 1000000 cosines and summing them with 1 threads took 0.095832s
$ OMP_NUM_THREADS=2 ./loopc
Computing 1000000 cosines and summing them with 2 threads took 0.047637s
$ OMP_NUM_THREADS=4 ./loopc
Computing 1000000 cosines and summing them with 4 threads took 0.024498s
$ OMP_NUM_THREADS=8 ./loopc
Computing 1000000 cosines and summing them with 8 threads took 0.011785s
फोरट्रान संस्करण के लिए, यह देता है:
$ gfortran -O3 -fopenmp loop.f90 -o loopf
$ OMP_NUM_THREADS=1 ./loopf
Computing 1000000 cosines and summing them with 1 threads took 0.0915s
$ OMP_NUM_THREADS=2 ./loopf
Computing 1000000 cosines and summing them with 2 threads took 0.0472s
$ OMP_NUM_THREADS=4 ./loopf
Computing 1000000 cosines and summing them with 4 threads took 0.0236s
$ OMP_NUM_THREADS=8 ./loopf
Computing 1000000 cosines and summing them with 8 threads took 0.0118s
निर्माण के लिए OpenMP समानांतर का उपयोग करते हुए दो वैक्टर का जोड़
void parallelAddition (unsigned N, const double *A, const double *B, double *C)
{
unsigned i;
#pragma omp parallel for shared (A,B,C,N) private(i) schedule(static)
for (i = 0; i < N; ++i)
{
C[i] = A[i] + B[i];
}
}
यह उदाहरण थ्रेड्स की एक टीम ( OMP_NUM_THREADS
environtment चर द्वारा निर्दिष्ट), उदाहरण के लिए दो वेक्टर ( A
और B
को C
) OMP_NUM_THREADS
और प्रत्येक थ्रेड को कार्य का एक हिस्सा असाइन करता है (इस उदाहरण में, schedule(static)
माध्यम से सांख्यिकीय रूप से असाइन किया गया अभिव्यक्ति)।
private(i)
वैकल्पिकता के संबंध में टिप्पणी अनुभाग देखें।