многопоточность — c ++ openmp для максимального уменьшения значения цикла во время выполнения цикла

При вычислении максимального сокращения внутри параллельного цикла for, каково значение переменной максимального сокращения в промежуточные моменты времени во время выполнения цикла? Это максимум только для определенного потока или это максимум всех потоков?

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

Например:

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

int main(int argc, char *argv[]) {

double randomarray[10];
//initialize the random array

double outputarray[10];
double currentmax = 0;

#pragma omp parallel for reduction(max:currentmax)
for( i=0;i<10; i++) {

if(randomarray[i] > currentmax)
{
currentmax = randomarray[i];
}

output[i]=randomarray[i]/currentmax;
// is this current max for the currently
// executing thread or all threads?
}

}

0

Решение

Это максимум только для определенного потока или это максимум всех потоков?

Это частное значение «на поток» в параллельной области OpenMP.

Следующий фрагмент кода может реализовать то, что вы хотите сделать, но это не кажется таким значимым.

#pragma omp parallel for
for( i=0;i<10; i++) {
double local_max;

#pragma omp critical
{
if(randomarray[i] > currentmax)
{
currentmax = randomarray[i];
}
local_max = currentmax;
}

output[i]=randomarray[i]/local_max;
}
1

Другие решения

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

Из спецификаций OpenMP 4:

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

2

Другие ответы ясно дали понять, что максимальное сокращение openmp не обеспечивает необходимую мне функциональность. Поэтому я нашел другой способ реализовать его с помощью атомарной операции max, определенной ниже:

inline double __sync_fetch_and_max_double(double* address, double val) {
int64_t* address_as_int64 = (int64_t*)address;
int64_t old = *address_as_int64, assumed;
do {
assumed = old;
double assumed_double = *((double*)&assumed);
double min = (val > assumed_double) ? val : assumed_double;
old = __sync_val_compare_and_swap(address_as_int64, assumed,
*((int64_t*)&min));
} while (assumed != old);
return *((double *)&old);
}

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

Модифицированный код выглядит так:

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

int main(int argc, char *argv[]) {

double randomarray[10];
//initialize the random array

double outputarray[10];
double currentmax = 0;

#pragma omp parallel for
for( i=0;i<10; i++) {

__sync_fetch_and_max_double(&currentmax,randomarray[i]);

output[i]=randomarray[i]/currentmax; //max among all threads

}

}
0
По вопросам рекламы [email protected]