省略非必要代码:
double* max_of_two(double *r,double *n);
int npoints = 1000000;
double* xy = (double*)malloc(2*npoints*sizeof(double));
double zero_coord[2] = {0.0,0.0};
double max_coord[2] = {0.0,0.0};
#pragma omp declare reduction\
(takemax:double*:omp_out=max_of_two(omp_out,omp_in)) \
initializer(omp_priv=zero_coord)
#pragma omp parallel for reduction(takemax:max_coord)
for (int i=0; i<npoints; i++) {
max_coord = max_of_two(max_coord,xy+2*i);
}
这会出现错误:
error: '#pragma omp declare reduction' initializer refers to variable 'zero_coord' which is not 'omp_priv' nor 'omp_orig'
这很奇怪,因为在更简单的代码中我可以初始化omp_priv=-1
等等。
有几个问题:OpenMP 允许按元素减少数组。对于堆栈数组,编译器希望使用按元素减少操作并寻找类型的减少
double
。如果您想在双精度对上定义减少,则应使用此类类型。对于这种类型,您可以简单地用
omp_priv = {0,0}
或进行初始化omp_priv = omp_orig
(适用于最大值,但不适用于一般情况)。omp_priv
放弃不同于和 的变量的主要原因omp_orig
是变量作用域的问题。一般变量不一定在初始化范围内可见。如果要从(全局)变量初始化,则需要将变量包装在函数中并从初始化子句initializer(init(&omp_priv))
或调用此函数initializer(omp_priv = init())
。以下内容使用 gcc 和 clang 进行编译和执行: