Поиск…


Вступление

В этом разделе рассматриваются основы параллелизма в C ++ с использованием OpenMP. OpenMP документируется более подробно в теге OpenMP .

Параллелизм или параллелизм подразумевают выполнение кода одновременно.

замечания

OpenMP не требует каких-либо специальных заголовков или библиотек, поскольку это встроенная функция компилятора. Однако, если вы используете какие-либо функции OpenMP API, такие как omp_get_thread_num() , вам нужно будет omp.h и его библиотеку.

Операторы pragma OpenMP игнорируются, когда опция OpenMP не включена во время компиляции. Вы можете обратиться к опции компилятора в руководстве вашего компилятора.

  • GCC использует -fopenmp
  • Кланг использует -fopenmp
  • MSVC использует /openmp

OpenMP: параллельные разделы

Этот пример иллюстрирует основы выполнения разделов кода параллельно.

Поскольку OpenMP является встроенной функцией компилятора, он работает с любыми поддерживаемыми компиляторами без включения каких-либо библиотек. Возможно, вы захотите включить omp.h если вы хотите использовать какие-либо функции OpenMP API.

Образец кода

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;

Выходы

Этот пример дает 2 возможных выхода и зависит от операционной системы и оборудования. Результат также иллюстрирует проблему состояния гонки, которая возникла бы из такой реализации.

ВЫХОД A ВЫХОД B
начать привет мир начать мир привет

OpenMP: параллельные разделы

В этом примере показано, как выполнять куски кода параллельно

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";

Выход

  • начать привет мир навсегда конец
  • начать мир привет навсегда конец
  • начать привет навсегда
  • начинать навсегда hello world end

Поскольку порядок выполнения не гарантируется, вы можете наблюдать за любым из вышеперечисленных результатов.

OpenMP: Параллельный для цикла

В этом примере показано, как разделить цикл на равные части и выполнить их параллельно.

//    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
...

* Пожалуйста, проявляйте особую осторожность, чтобы не изменять размер вектора, который используется параллельно для циклов, поскольку выделенные индексы диапазона не обновляются автоматически .

OpenMP: параллельная сборка / сокращение

Этот пример иллюстрирует концепцию выполнения сокращения или сбора с использованием std::vector и OpenMP.

Предположим, у нас есть сценарий, когда мы хотим, чтобы несколько потоков помогли нам создать кучу материала, int используется здесь для простоты и может быть заменен другими типами данных.

Это особенно полезно, когда вам нужно объединить результаты с ведомыми устройствами, чтобы избежать сбоев в сегментировании или нарушения доступа к памяти, и не хотите использовать библиотеки или пользовательские библиотеки контейнеров синхронизации.

//    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
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow