最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

OpenMP declare reduction: initializer refers to variable which is not 'omp_priv' nor 'omp_orig'

programmeradmin4浏览0评论

Leaving out non-essential code:

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

This gives the error:

error: '#pragma omp declare reduction' initializer refers to variable 'zero_coord' which is not 'omp_priv' nor 'omp_orig'

Which is strange because in simpler code I can initialize omp_priv=-1 and such.

Leaving out non-essential code:

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

This gives the error:

error: '#pragma omp declare reduction' initializer refers to variable 'zero_coord' which is not 'omp_priv' nor 'omp_orig'

Which is strange because in simpler code I can initialize omp_priv=-1 and such.

Share asked Mar 7 at 17:20 Victor EijkhoutVictor Eijkhout 5,9072 gold badges26 silver badges31 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 2

There are several issues: OpenMP allows to reduce arrays element-wise. For stack arrays, the compiler wants to use an element-wise reduction operation and looks for a reduction for type double. If you want to define the reduction on a pair of doubles, you should use such type.

For such type you can simply initialize with omp_priv = {0,0} or omp_priv = omp_orig (works for max, but not for the general case).

The main reason for discarding variables different from omp_priv and omp_orig is a question of variable scoping. General variables are not necessarily visible in the scope of the initialization. If you want to initialize from a (global) variable, you would need to wrap the variable in a function and call this function from the initializer clause initializer(init(&omp_priv)) or initializer(omp_priv = init()).

The following compiles and executes for me using gcc and clang:

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

typedef struct {
  double x;
  double y;
} pair;

pair max_of_two(pair r, pair n) {
  r.x = r.x > n.x ? r.x : n.x;
  r.y = r.y > n.y ? r.y : n.y;
  return r;
}

int main() {
  int npoints = 100;
  pair *xy = (pair *)malloc(npoints * sizeof(pair));

  pair max_coord = {0.0, 0.0};

#pragma omp declare reduction(takemax                                          \
:pair : omp_out = max_of_two(omp_out, omp_in)) initializer(omp_priv = {0, 0})

#pragma omp parallel for reduction(takemax : max_coord)
  for (int i = 0; i < npoints; i++) {
    xy[i].x = sin(i + .5);
    xy[i].y = cos(i + .5);
    max_coord = max_of_two(max_coord, xy[i]);
  }

  printf("max_coord = %lf, %lf\n", max_coord.x, max_coord.y);
}

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论