कार्य निर्भरता ओपनएमपी
मेरे 5 कार्य A, B, C, D, E हैं।
DI को निष्पादित करने के लिए B, C की आवश्यकता होती है, जिसे निष्पादित करने के लिए EI को निष्पादित करने के लिए A, D की आवश्यकता होती है।
मैंने यह कोशिश की है
int main()
{
#pragma omp parallel num_threads(5)
{
long t1 = clock();
int a = 0, b = 0, c = 0, d = 0, e = 0;
int th = omp_get_thread_num();
if (th == 0) {
a += A();
printf("A is finished after %d\n", clock() - t1);
}
if (th == 1) {
b += B();
printf("B is finished after %d\n", clock() - t1);
}
if (th == 2) {
c += C();
printf("C is finished after %d\n", clock() - t1);
}
if (th == 3 && (b == 1 && c == 1)) {
d += D();
printf("D is finished after %d\n", clock() - t1);
}
if (th == 4 && (a == 1 && d == 1)) {
e += E();
printf("E is finished after %d\n", clock() - t1);
}
}
return 0;
}
लेकिन डी, ई निष्पादित नहीं किया है
ये सभी फ़ंक्शन डीबगिंग उद्देश्य के लिए अब तक 1 लौटाते हैं
जवाब
चर a
, b
, c
और d,
करने के लिए इस्तेमाल नहीं किया जा सकता संवाद सूत्र के बीच क्योंकि वे सभी कर रहे हैं निजी । इसलिए, प्रत्येक धागे की अपनी निजी प्रति है। इसके अलावा, आमतौर पर उन्हें सिंक्रनाइज़ेशन उद्देश्यों के लिए उपयोग करना एक अच्छा विचार नहीं है।
आपके कोड में thread=3
कभी भी इंतजार नहीं होगा if (th == 3 && (b == 1 && c == 1))
क्योंकि:
b
औरc
निजी हैं, इसलिएthread=3
हैb=0
औरc=0
क्या अन्य थ्रेड उनके लिए किया है की परवाह किए बिना प्रतियां चर केb=0
औरc=0
।- नहीं है कुछ भी नहीं कह रहा है कि धागा प्रतीक्षा करने के लिए ( जैसे, कुछ तुल्यकालन एक जैसे निर्माता)।
यदि आप चाहते हैं कि धागे एक-दूसरे का इंतजार करें तो omp barrier
इसके बजाय उपयोग करें । सभी थ्रेड्स को उनकी संगणना के साथ आगे बढ़ने से पहले अवरोध को कॉल करना होगा।
int main()
{
#pragma omp parallel num_threads(5)
{
long t1 = clock();
int a = 0, b = 0, c = 0, d = 0, e = 0;
int th = omp_get_thread_num();
if (th == 0) {
a += A();
printf("A is finished after %d\n", clock() - t1);
}
if (th == 1) {
b += B();
printf("B is finished after %d\n", clock() - t1);
}
if (th == 2) {
c += C();
printf("C is finished after %d\n", clock() - t1);
}
// Threads will wait for each other here
#pragma omp barrier
if (th == 3) {
d += D();
printf("D is finished after %d\n", clock() - t1);
}
// Threads will wait for each other here
#pragma omp barrier
if (th == 4) {
e += E();
printf("E is finished after %d\n", clock() - t1);
}
}
return 0;
}
OpenMP 4.0 मानक पर जारी एक सुविधा पर निर्भरता वाले कार्यों का उपयोग करने के लिए एक अधिक परिष्कृत दृष्टिकोण होगा। इस थ्रेड पर यह सुविधा कैसे काम करती है, इसके बारे में पहले से ही एक अच्छी व्याख्या है ।
int a = 0, b = 0, c = 0, d = 0, e = 0;
#pragma omp parallel num_threads(5) shared(a, b, c, d)
{
#pragma omp single nowait
{
long t1 = clock();
int th = omp_get_thread_num();
#pragma omp task depend (out:a)
{
a += A();
printf("A is finished after %d\n", clock() - t1);
}
#pragma omp task depend (out:b)
{
b += B();
printf("B is finished after %d\n", clock() - t1);
}
#pragma omp task depend (out:c)
{
c += C();
printf("C is finished after %d\n", clock() - t1);
}
#pragma omp task depend (in:a, b) depend(out:d)
{
d += D();
printf("D is finished after %d\n", clock() - t1);
}
#pragma omp task depend (in:a, b)
{
e += E();
printf("E is finished after %d\n", clock() - t1);
}
}
}
return 0;
}
डेटा निर्भरता वाले कार्यों का उपयोग करने के लिए एक उचित OpenMP समाधान होगा:
#pragma omp parallel num_threads(3)
#pragma omp single
{
double t1 = omp_wtime();
int a = 0, b = 0, c = 0, d = 0, e = 0;
#pragma omp task shared(a) depend(out: a)
{
a += A();
printf("A is finished after %f\n", omp_wtime() - t1);
}
#pragma omp task shared(b) depend(out: b)
{
b += B();
printf("B is finished after %f\n", omp_wtime() - t1);
}
#pragma omp task shared(c) depend(out: c)
{
c += C();
printf("C is finished after %f\n", omp_wtime() - t1);
}
#pragma omp task shared(b,c,d) depend(in: b,c) depend(out: d)
{
d += D();
printf("D is finished after %f\n", omp_wtime() - t1);
}
#pragma omp task shared(a,d,e) depend(in: a,d)
{
e += E();
printf("E is finished after %f\n", omp_wtime() - t1);
}
}
इधर, कार्य A
के मूल्य के लिए निर्माता के रूप में चिह्नित किया गया है a
के साथ depend(out: a)
और काम D
के निर्माता के रूप में चिह्नित किया गया है d
के साथ depend(out: d)
। टास्क E
को उन दो मूल्यों के उपभोक्ता के रूप में चिह्नित किया गया है depend(in: a,d)
। आउटपुट (निर्माता) और इनपुट (उपभोक्ता) निर्भरता के बाद, ओपनएमपी रनटाइम एक निष्पादन डीएजी (निर्देशित एसाइक्लिक ग्राफ) बनाता है जो इसे सभी कार्यों के निष्पादन का उचित क्रम बताता है। आपको पाँच धागों की भी आवश्यकता नहीं है - तीन पर्याप्त हैं।
एक single
निर्माण के अंदर कार्य कोड होना बहुत ही मुहावरेदार OpenMP है।
टास्क निर्भरताएं 2013 में OpenMP 4.0 द्वारा शुरू की गई थीं, इसलिए MSVC ++ को छोड़कर किसी भी आधुनिक संकलक को उस सुविधा के लिए समर्थन प्रदान करना चाहिए।