Zoeken…


Opmerkingen

Een veel voorkomende valkuil is om te geloven dat alle threads van een parallelle regio taken moeten instantiëren (maken), maar dit is meestal niet het geval, tenzij je zoveel taken wilt maken als het aantal threads maal het aantal te verwerken elementen. Daarom vindt u in OpenMP-taakcodes iets vergelijkbaars met

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

Parallelle verwerking van een c ++ -lijstcontainer met OpenMP-taken

#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;
}

Dit voorbeeld simuleert de verwerking van een STL-lijst (met de naam lst in de code) parallel via de OpenMP- #pragma omp task (met behulp van de #pragma omp task ). Het voorbeeld maakt / instantieert één OpenMP-taak voor elk element in lst en de OpenMP-threads voeren de taken uit zodra ze klaar zijn om te worden uitgevoerd.

$ 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

Recursieve berekening voor pi met behulp van OpenMP-taken

De onderstaande code berekent de waarde van PI met behulp van een recursieve aanpak. Wijzig de waarde MAX_PARALLEL_RECURSIVE_LEVEL om te bepalen bij welke recursiediepte het maken van taken wordt gestopt. Met deze aanpak om parallellisme te creëren uit recursieve toepassingen: hoe meer taken u maakt, hoe meer parallelle taken worden gemaakt, maar ook hoe minder werk per taak. Het is dus handig om met de applicatie te experimenteren om te begrijpen op welk niveau het creëren van verdere taken niet ten goede komt aan de prestaties.

#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
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow