Sök…


Introduktion

Detta ämne täcker grunderna för samtidighet i C ++ med OpenMP. OpenMP dokumenteras mer detaljerat i OpenMP-taggen .

Parallellism eller samtidighet innebär att koden körs samtidigt.

Anmärkningar

OpenMP kräver inga speciella rubriker eller bibliotek eftersom det är en inbyggd kompilatorfunktion. Men om du använder någon OpenMP API-funktioner som omp_get_thread_num() måste du inkludera omp.h och dess bibliotek.

OpenMP- pragma uttalanden ignoreras när alternativet OpenMP inte är aktiverat under sammanställningen. Du kanske vill hänvisa till kompilatoralternativet i din kompilers manual.

  • GCC använder -fopenmp
  • Clang använder -fopenmp
  • MSVC använder /openmp

OpenMP: Parallella avsnitt

Detta exempel illustrerar grunderna för att köra delar av kod parallellt.

Eftersom OpenMP är en inbyggd kompilatorfunktion, fungerar den på alla kompilatorer som stöds utan att inkludera bibliotek. Du kanske vill inkludera omp.h om du vill använda någon av openMP API-funktionerna.

Exempelkod

std::cout << "begin ";
//    This pragma statement hints the compiler that the
//    contents within the { } are to be executed in as
//    parallel sections using openMP, the compiler will
//    generate this chunk of code for parallel execution
#pragma omp parallel sections
{
    //    This pragma statement hints the compiler that
    //    this is a section that can be executed in parallel
    //    with other section, a single section will be executed
    //    by a single thread.
    //    Note that it is "section" as opposed to "sections" above
    #pragma omp section
    {
        std::cout << "hello " << std::endl;
        /** Do something **/
    }
    #pragma omp section
    {
        std::cout << "world " << std::endl;
        /** Do something **/
    }
}
//    This line will not be executed until all the
//    sections defined above terminates
std::cout << "end" << std::endl;

utgångar

Detta exempel ger två möjliga utgångar och är beroende av operativsystem och hårdvara. Utgången illustrerar också ett konkurrenstillstånd problem som skulle uppstå från en sådan implementering.

UTGÅNG A UTGÅNG B
börja hej världsslut börja världen hej slut

OpenMP: Parallella avsnitt

Detta exempel visar hur man kör koder bitar parallellt

std::cout << "begin ";
//    Start of parallel sections
#pragma omp parallel sections
{
    //    Execute these sections in parallel
    #pragma omp section
    {
        ... do something ...
        std::cout << "hello ";
    }
    #pragma omp section
    {
        ... do something ...
        std::cout << "world ";
    }
    #pragma omp section
    {
        ... do something ...
        std::cout << "forever ";
    }
}
//    end of parallel sections
std::cout << "end";

Produktion

  • börja hej världen för evigt slut
  • börja världen hej evigt slut
  • börja hej för evigt världsslut
  • börja för evigt hej världsslut

Eftersom exekveringsorder inte garanteras, kan du observera någon av ovanstående utgångar.

OpenMP: Parallel For Loop

Detta exempel visar hur man delar upp en slinga i lika delar och körs parallellt.

//    Splits element vector into element.size() / Thread Qty
//    and allocate that range for each thread.
#pragma omp parallel for
for    (size_t i = 0; i < element.size(); ++i)
    element[i] = ...

//    Example Allocation (100 element per thread)
//    Thread 1 : 0 ~ 99
//    Thread 2 : 100 ~ 199
//    Thread 2 : 200 ~ 299
//    ...

//    Continue process
//    Only when all threads completed their allocated
//    loop job
...

* Var noga med att inte ändra storleken på vektorn som används parallellt för slingor eftersom tilldelade intervallindex inte uppdateras automatiskt .

OpenMP: Parallell samling / minskning

Detta exempel illustrerar ett koncept för att utföra reduktion eller samling med std::vector och OpenMP.

Antas att vi har ett scenario där vi vill att flera trådar ska hjälpa oss att generera en massa saker, int används här för enkelhet och kan ersättas med andra datatyper.

Detta är särskilt användbart när du behöver slå samman resultat från slavar för att undvika segmentfel eller minnesåtkomstbrott och inte vill använda bibliotek eller anpassade synkroniseringsbehållarbibliotek.

//    The Master vector
//    We want a vector of results gathered from slave threads
std::vector<int> Master;    

//    Hint the compiler to parallelize this { } of code
//    with all available threads (usually the same as logical processor qty)
#pragma omp parallel
{
    //    In this area, you can write any code you want for each
    //    slave thread, in this case a vector to hold each of their results
    //    We don't have to worry about how many threads were spawn or if we need
    //    to repeat this declaration or not.
    std::vector<int> Slave;

    //    Tell the compiler to use all threads allocated for this parallel region
    //    to perform this loop in parts. Actual load appx = 1000000 / Thread Qty
    //    The nowait keyword tells the compiler that the slave threads don't
    //    have to wait for all other slaves to finish this for loop job
    #pragma omp for nowait
    for (size_t i = 0; i < 1000000; ++i
    {
        /* Do something */
        ....
        Slave.push_back(...);
    }

    //    Slaves that finished their part of the job
    //    will perform this thread by thread one at a time
    //    critical section ensures that only 0 or 1 thread performs
    //    the { } at any time
    #pragma omp critical
    {
        //    Merge slave into master
        //    use move iterators instead, avoid copy unless
        //    you want to use it for something else after this section
        Master.insert(Master.end(), 
                      std::make_move_iterator(Slave.begin()), 
                      std::make_move_iterator(Slave.end()));
    }
}

//    Have fun with Master vector
...


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