Поиск…


параметры

пункт параметр
private Список частных переменных, разделенных запятыми
firstprivate Как private , но инициализируется значением переменной перед входом в цикл
lastprivate Как private , но переменная получит значение, соответствующее последней итерации цикла при выходе
reduction оператор сокращения : список соответствующих редукционных переменных, разделенных запятыми
schedule static , dynamic , guided , auto или runtime с дополнительным размером блока после комы для 3-х бывших
collapse Количество идеально вложенных циклов для развала и параллелизации
ordered Сообщает, что некоторые части цикла должны быть сохранены в порядке (эти части будут конкретно идентифицированы с некоторыми ordered предложениями внутри тела цикла)
nowait Удалите скрытый барьер, существующий по умолчанию в конце конструкции цикла

замечания

Смысл положения о schedule заключается в следующем:

  • static[,chunk] : распределить статически (что означает, что дистрибутив выполняется перед входом в цикл) итерации цикла в пакетном размере chunk в циклическом режиме. Если chunk не указан, то куски как можно более ровны, и каждый поток получает не более одного из них.
  • dynamic[,chunk] : распределить итерации цикла между потоками пакетами размером chunk с политикой с первым пришел-первым, пока не останется партия. Если не указано, chunk установлен в 1
  • guided[,chunk] : как dynamic но с партиями, размеры которых становятся все меньше и меньше, до 1
  • auto : Позвольте компилятору и / или библиотеке времени выполнения решить, что лучше всего подходит
  • runtime : принять решение во время выполнения с OMP_SCHEDULE переменной среды OMP_SCHEDULE . Если во время выполнения переменная среды не определена, будет использоваться планирование по умолчанию

По умолчанию для schedule используется определение реализации . Во многих средах это static , но также может быть dynamic или вполне может быть auto . Поэтому будьте осторожны, чтобы ваша реализация не косвенно опиралась на нее без явной настройки.

В приведенных выше примерах мы использовали сплавленную форму, parallel for или parallel do . Однако конструкцию цикла можно использовать, не сливая ее с parallel директивой, в виде #pragma omp for [...] или !$omp do [...] автономной директивы в parallel области.

Только для версии Fortran индексированная переменная цикла цикла (s) всегда является private по умолчанию. Поэтому нет необходимости явно объявлять их private (хотя делать это не является ошибкой).
Для версий C и C ++ индексы цикла аналогичны любым другим переменным. Поэтому, если их область действия выходит за пределы параллельного цикла (s) (то есть, если они не объявлены как for ( int i = ...) а скорее как int i; ... for ( i = ... ) тогда они должны быть объявлены private .

Типичный пример в C

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

#define N 1000000

int main() {
    double sum = 0;

    double tbegin = omp_get_wtime();
    #pragma omp parallel for reduction( +: sum )
    for ( int i = 0; i < N; i++ ) {
        sum += cos( i );
    }
    double wtime = omp_get_wtime() - tbegin;

    printf( "Computing %d cosines and summing them with %d threads took %fs\n",
            N, omp_get_max_threads(), wtime );

    return sum;
}

В этом примере мы просто вычислим 1 миллион косинусов и суммируем их значения параллельно. Мы также выполняем время, чтобы увидеть, влияет ли распараллеливание на производительность. Наконец, поскольку мы измеряем время, мы должны убедиться, что компилятор не будет оптимизировать работу, которую мы сделали, поэтому мы делаем вид, что используем результат, просто вернув его.

Тот же пример в Фортране

program typical_loop
    use omp_lib
    implicit none
    integer, parameter :: N = 1000000, kd = kind( 1.d0 )
    real( kind = kd ) :: sum, tbegin, wtime
    integer :: i

    sum = 0

    tbegin = omp_get_wtime()
    !$omp parallel do reduction( +: sum )
    do i = 1, N
        sum = sum + cos( 1.d0 * i )
    end do
    !$omp end parallel do
    wtime = omp_get_wtime() - tbegin

    print "( 'Computing ', i7, ' cosines and summing them with ', i2, &
        & ' threads took ', f6.4,'s' )", N, omp_get_max_threads(), wtime

    if ( sum > N ) then
        print *, "we only pretend using sum"
    end if
end program typical_loop

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

Компиляция и запуск примеров

На машине с 8 ядрами, использующей GCC версии 4.4, коды C могут быть скомпилированы и выполняться следующим образом:

$ gcc -std=c99 -O3 -fopenmp loop.c -o loopc -lm
$ OMP_NUM_THREADS=1 ./loopc
Computing 1000000 cosines and summing them with 1 threads took 0.095832s
$ OMP_NUM_THREADS=2 ./loopc
Computing 1000000 cosines and summing them with 2 threads took 0.047637s
$ OMP_NUM_THREADS=4 ./loopc
Computing 1000000 cosines and summing them with 4 threads took 0.024498s
$ OMP_NUM_THREADS=8 ./loopc
Computing 1000000 cosines and summing them with 8 threads took 0.011785s

Для версии Fortran она дает:

$ gfortran -O3 -fopenmp loop.f90 -o loopf
$ OMP_NUM_THREADS=1 ./loopf
Computing 1000000 cosines and summing them with  1 threads took 0.0915s
$ OMP_NUM_THREADS=2 ./loopf
Computing 1000000 cosines and summing them with  2 threads took 0.0472s
$ OMP_NUM_THREADS=4 ./loopf
Computing 1000000 cosines and summing them with  4 threads took 0.0236s
$ OMP_NUM_THREADS=8 ./loopf
Computing 1000000 cosines and summing them with  8 threads took 0.0118s

Добавление двух векторов с использованием OpenMP parallel для построения

void parallelAddition (unsigned N, const double *A, const double *B, double *C)
{
    unsigned i;

    #pragma omp parallel for shared (A,B,C,N) private(i) schedule(static)
    for (i = 0; i < N; ++i)
    {
        C[i] = A[i] + B[i];
    }
}

Этот пример добавляет два вектора ( A и B в C ), OMP_NUM_THREADS группу потоков ( OMP_NUM_THREADS указанную переменной OMP_NUM_THREADS OMP_NUM_THREADS) и назначая каждому потоку кусок работы (в этом примере статически назначается по schedule(static) выражение).

См. Раздел замечаний относительно private(i) варианта.



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow