Sök…


Anmärkningar

En vanlig fallgrop är att tro att alla trådar i ett parallellt område borde initiera (skapa) uppgifter men detta är inte vanligtvis fallet om du inte vill skapa så många uppgifter som antalet trådar gånger antalet element som ska behandlas. Därför hittar du i OpenMP-uppgiftskoder något liknande

#pragma omp parallel
#pragma omp single
...
   #pragma omp task
   { code for a given task; }
...

Parallell behandling av en c ++ listbehållare med OpenMP-uppgifter

#include <omp.h>
#include <unistd.h>
#include <iostream>
#include <list>

static void processElement (unsigned n)
{
    // Tell who am I. The #pragma omp critical ensures that
    // only one thread sends data to std::cout
    #pragma omp critical
    std::cout <<
      "Thread " << omp_get_thread_num() << " processing element " << n
      << std::endl;

    // Simulate some work
    usleep (n*1000);
}

int main (void)
{
    std::list<unsigned> lst;

    // Fill the list
    for (unsigned u = 0; u < 16; ++u)
            lst.push_back (1+u);

    // Now process each element of the list in parallel

    #pragma omp parallel  // Create a parallel region
    #pragma omp single    // Only one thread will instantiate tasks
    {
            for (auto element : lst)
            {
                    #pragma omp task firstprivate (element)
                    processElement (element);
            }

            // Wait for all tasks to be finished
            #pragma omp taskwait
    }

    return 0;
}

Detta exempel simulerar behandlingen av en STL-lista (benämnd lst i koden) parallellt genom OpenMP-uppgiftskonstruktioner (med #pragma omp task ). Exemplet skapar / initierar en OpenMP-uppgift för varje element i lst och OpenMP-trådarna kör uppgifterna så snart de är redo att köras.

$ OMP_NUM_THREADS=4 ./a.out
Thread 0 processing element 16
Thread 3 processing element 3
Thread 2 processing element 1
Thread 1 processing element 2
Thread 2 processing element 4
Thread 1 processing element 5
Thread 3 processing element 6
Thread 2 processing element 7
Thread 1 processing element 8
Thread 3 processing element 9
Thread 2 processing element 10
Thread 1 processing element 11
Thread 0 processing element 15
Thread 3 processing element 12
Thread 2 processing element 13
Thread 1 processing element 14

Rekursiv beräkning för pi med OpenMP-uppgifter

Koden nedan beräknar värdet på PI med hjälp av en rekursiv metod. Ändra MAX_PARALLEL_RECURSIVE_LEVEL värdet för att bestämma på vilket rekursionsdjup som slutar skapa uppgifter. Med denna metod för att skapa parallellitet ur rekursiva applikationer: ju fler uppgifter du skapar, desto mer parallella uppgifter skapas men också mindre arbete per uppgift. Så det är bekvämt att experimentera med applikationen för att förstå på vilken nivå den skapar ytterligare uppgifter inte gynnar vad gäller prestanda.

#include <stdio.h>
#include <omp.h>

double pi_r (double h, unsigned depth, unsigned maxdepth, unsigned long long begin, unsigned long long niters)
{
    if (depth < maxdepth)
    {
        double area1, area2;

        // Process first half
        #pragma omp task shared(area1)
        area1 = pi_r (h, depth+1, maxdepth, begin, niters/2-1);

        // Process second half
        #pragma omp task shared(area2)
        area2 = pi_r (h, depth+1, maxdepth, begin+niters/2, niters/2);

        #pragma omp taskwait

        return area1+area2;
    }
    else
    {

        unsigned long long i;
        double area = 0.0;

        for (i = begin; i <= begin+niters; i++)
        {
            double x = h * (i - 0.5);
            area += (4.0 / (1.0 + x*x));
        }

        return area;
    }
}

double pi (unsigned long long niters)
{
    double res;
    double h = 1.0 / (double) niters;

    #pragma omp parallel shared(res)
    {
#define MAX_PARALLEL_RECURSIVE_LEVEL 4

        #pragma omp single
        res = pi_r (h, 0, MAX_PARALLEL_RECURSIVE_LEVEL, 1, niters);
    }
    return res * h;
}


int main (int argc, char *argv[])
{
#define NITERS (100*1000*1000ULL)

    printf ("PI (w/%d iters) is %lf\n", NITERS, pi(NITERS));

    return 0;
}


Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow