使用openmp使用依赖于外循环的内循环优化并行嵌套循环

时间:2019-05-24 10:04:20

标签: c++ c openmp

如何使用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 :(得分:0)

从OpenMP 4.0开始,您可以编写own reduction

这个想法是:

  • 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;
}

没有-fopenmpreal 0m3.727s

使用-fopenmpreal 0m0.835s