Локальные переменные в цикле for openmp - PullRequest
0 голосов
/ 07 ноября 2018

Я только начал программировать с openmp и пытаюсь распараллелить цикл for с переменной, которая мне нужна вне цикла. Как то так:

float a = 0;
for (int i = 0; i < x; i++)
{
    int x = algorithm();
    /* Each loop, x have a different value*/
    a = a + x;
}
cout << a;

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

Как я могу это сделать?

Ответы [ 3 ]

0 голосов
/ 07 ноября 2018

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

float a = 0;//Global and will be shared.
#pragma omp parallel 
{
    float y = 0;//Private to each thread
#pragma omp for
    for(int i = 0; i < x; i++)
         y += algorithm();//Better practice is to not use same variable as loop termination variable.
//Still inside parallel
#pragma omp atomic
    a += y;
 }
cout << a;
0 голосов
/ 07 ноября 2018

Используйте предложение #pragma omp parallel for reduction(+:a) перед циклом for

Переменная

, объявленная в цикле for, является локальной, а также счетчиками цикла переменные, объявленные вне блока #pragma omp parallel, являются общими по умолчанию, если не указано иное (см. пункты shared, private, firstprivate). Следует соблюдать осторожность при обновлении общих переменных, так как может возникнуть состояние гонки. В этом случае предложение reduction(+:a) указывает, что a является общей переменной, для которой выполняется сложение в каждом цикле. Потоки будут автоматически отслеживать общую сумму, которую нужно добавить, и безопасно увеличивать a в конце цикла.

Оба кода ниже эквивалентны:

float a = 0.0f;
int n=1000;
#pragma omp parallel shared(a) //spawn the threads
{
float acc=0;        // local accumulator to each thread
#pragma omp for     // iterations will be shared among the threads
for (int i = 0; i < n; i++){
      float x = algorithm(i); //do something
      acc += x;     //local accumulator increment
  } //for
#omp pragma atomic
a+=acc; //atomic global accumulator increment: done on thread at a time
} //end parallel region, back to a single thread
cout << a;

Эквивалентно:

float a = 0.0f;
int n=1000;
#pragma omp parallel for reduction(+:a)
for (int i = 0; i < n; i++){
    int x = algorithm(i);
    a += x;
    } //parallel for
cout << a;

Обратите внимание, что вы не можете создать цикл for с условием остановки i<x, где x - локальная переменная, определенная в цикле.

0 голосов
/ 07 ноября 2018

Существует множество механизмов достижения цели, но самый простой - использовать параллельное сокращение OpenMP:

float a = 0.0f;
#pragma omp parallel for reduction(+:a)
for(int i = 0; i < x; i++) 
  a += algorithm();
cout << a;
...