Определяемое пользователем сокращение не возвращает ожидаемый результат при каждом запуске - PullRequest
0 голосов
/ 12 февраля 2019

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

Я попытался проверить значения min и max в циклах for, и кажется, что внутри распараллеленных циклов forминимальное и максимальное значения соответствуют ожидаемым.Однако в конце цикла min и max полностью содержат значения wacko.

Мое определение сокращения

typedef struct {
    int value;
    int index_i;
    int index_j;
} Point;

#pragma omp declare reduction(minimum : Point : \
    omp_out = omp_in.value < omp_out.value ? omp_in : omp_out) \
    initializer(omp_priv = {INT_MAX, 0, 0})
#pragma omp declare reduction(maximum : Point : \
    omp_out = omp_in.value > omp_out.value ? omp_in : omp_out) \
    initializer(omp_priv = {0, 0, 0})

Инициализация массива 2d, где size равно 10000

for (int i = 0; i < size; i++) {
    for (int j = 0; j < size; j++) {
        matrix[i][j] = rand()%99;
    }
}

Распараллеленные циклы:

int i, j, total=0;
Point min, max;

#pragma omp parallel for reduction (+:total) reduction(minimum : min) reduction(maximum : max) private(j)
    for (i = 0; i < size; i++) {
        for (j = 0; j < size; j++) {
            total += matrix[i][j];

            if (matrix[i][j] < min.value) {
                min.value = matrix[i][j];
                min.index_i = i;
                min.index_j = j;
            }


            if (matrix[i][j] > max.value) {
                max.value = matrix[i][j];
                max.index_i = i;
                max.index_j = j;
            }
        }
    }

Ожидаемый результат: min = 0 по индексу (0, 70) и max = 98 по индексу (0, 20).

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

The min is -290390323 at index (21850, -9176672)
The max is 32595 at index (0, 0)

1 Ответ

0 голосов
/ 12 февраля 2019

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

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

Кроме того, обратите внимание, что для C на самом деле предложения инициализатора сокращения OpenMPпредоставить инициализаторы , в смысле термина стандарта C.Это не то же самое, что операторы присваивания, и разница особенно очевидна в вашем случае, когда элемент списка имеет тип структуры.Ваши инициализаторы хороши как инициализаторы, но они не являются допустимыми выражениями присваивания.Следовательно, они не могут использоваться для назначения начальных значений разделяемым переменным внутри параллельной области, поскольку инициализаторы появляются только как часть объявлений переменных.

...