कार्य निर्भरता ओपनएमपी

Nov 24 2020

मेरे 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 लौटाते हैं

जवाब

1 dreamcrash Nov 24 2020 at 16:58

चर a, b, cऔर d,करने के लिए इस्तेमाल नहीं किया जा सकता संवाद सूत्र के बीच क्योंकि वे सभी कर रहे हैं निजी । इसलिए, प्रत्येक धागे की अपनी निजी प्रति है। इसके अलावा, आमतौर पर उन्हें सिंक्रनाइज़ेशन उद्देश्यों के लिए उपयोग करना एक अच्छा विचार नहीं है।

आपके कोड में thread=3कभी भी इंतजार नहीं होगा if (th == 3 && (b == 1 && c == 1))क्योंकि:

  1. bऔर cनिजी हैं, इसलिए thread=3है b=0और c=0क्या अन्य थ्रेड उनके लिए किया है की परवाह किए बिना प्रतियां चर के b=0और c=0
  2. नहीं है कुछ भी नहीं कह रहा है कि धागा प्रतीक्षा करने के लिए ( जैसे, कुछ तुल्यकालन एक जैसे निर्माता)।

यदि आप चाहते हैं कि धागे एक-दूसरे का इंतजार करें तो 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;
}
2 HristoIliev Nov 24 2020 at 17:43

डेटा निर्भरता वाले कार्यों का उपयोग करने के लिए एक उचित 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 ++ को छोड़कर किसी भी आधुनिक संकलक को उस सुविधा के लिए समर्थन प्रदान करना चाहिए।