Оптимизация параллельного вложенного цикла с внутренним циклом, зависящим от внешнего цикла, используя openmp - PullRequest
1 голос
/ 24 мая 2019

Как мне получить лучшую оптимизацию для этого куска кода, используя openmp. Количество потоков - 6 , но производительность не улучшается.

Я пробовал разные варианты планирования, но не могу оптимизировать его лучше.Есть ли способ получить лучший результат?

int lenght = 40000;
int idx;
long *result = new long[ size ];

#pragma omp parallel for private(idx) schedule(dynamic)
for ( int i = 0; i < lenght; i++ ) {
    for ( int j = 0; j < i; j++  ) {
        idx = (int)( someCalculations( i, j ) );
        #pragma omp atomic
        result[ idx ] += 1;
    }
}

Этот фрагмент кода оптимизирует время расчета, но мне все еще нужен лучший результат.

Заранее спасибо.

1 Ответ

0 голосов
/ 24 мая 2019

Начиная с OpenMP 4.0 вы можете написать свое собственное сокращение .

Идея такова:

  • в цикле for, вы указываете компилятору уменьшить место, которое вы изменяете в каждом цикле.
  • , поскольку omp не знает, как уменьшить такой массив, вы должны написать свой собственный сумматор my_add, который просто сложит два массива.
  • Вы говорите omp, как использовать его в своем редукторе (myred)

#include <stdio.h>
#include <stdlib.h>

#define LEN 40000

int someCalculations(int i, int j)
{
    return i * j % 40000  ;
}

/* simple adder, just sum x+y in y */
long *my_add(long * x, long *y)
{
    int i;
 #pragma omp parallel for private(i)
    for (i = 0; i < LEN; ++i)
    {
        x[i] += y[i];
    }

    free(y);
    return x;

}

/* reduction declaration:
   name
   type
   operation to be performed
   initializer */
#pragma omp declare reduction(myred: long*:omp_out=my_add(omp_out,omp_in))\
    initializer(omp_priv=calloc(LEN, sizeof(long)))

int main(void)
{
    int i, j;
    long *result = calloc(LEN, sizeof *result);

// tell omp how to use it
#pragma omp parallel for reduction(myred:result) private (i, j)
    for (i = 0; i < LEN; i++) {
        for (j = 0; j < i; j++) {
            int idx = someCalculations(i, j);
            result[idx] += 1;
        }
    }

    // simple display, I store it in a file and compare 
    // result files with/without openmp to be sure it's correct...
    for (i = 0; i < LEN; ++i) {
        printf("%ld\n",  result[i]);
    }

    return 0;
}

Без -fopenmp: real 0m3.727s

С -fopenmp: real 0m0.835s

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...