Можно ли использовать редукционную переменную из аргумента, передаваемого по указателю, в потерянной подпрограмме C? - PullRequest
0 голосов
/ 14 сентября 2018

Я пытаюсь создать редукционную переменную внутри осиротевшей подпрограммы в C. Я понимаю, что мне нужно передать переменную по указателю в подпрограмму, чтобы убедиться, что она обрабатывается как общая (она является общей в охватывающей параллельной области),Однако, когда я пытаюсь скомпилировать компилятор, мне не нравится тот факт, что переменная является указателем (я думаю), и жалуется, что у него нет типа сокращения для указателей, т.е. с помощью компилятора cray я получаю эту ошибку:

CC-1642 craycc: ERROR File = main.c, Line = 33
  The OpenMP reduction clause does not accept pointer or reference types.
  #pragma omp for reduction(+:sum)

При использовании этого примера кода:

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

int myroutine(double *, double *, int);

int main(void){

  double a[100];
  double sum;
  int i;
  int n = 100;

  for(i=0;i<n;i++){
    a[i]=3.2;
  }


#pragma omp parallel shared(a,n,sum)
{
  myroutine(a, &sum, n);
}

  printf("sum = %lf\n",sum);

  return 0;
}

int myroutine(double *a, double *sum, int n){

  int i;

#pragma omp for reduction(+:sum)
  for(i=0;i<n;i++){
    *sum += a[i];
  }

  return 0;

}

Нужно ли выполнять копирование из переданной по указателю переменной в локальную переменную?Или есть другой способ добиться этого?

Ответы [ 2 ]

0 голосов
/ 14 сентября 2018

Обнаженный указатель в этой ситуации неоднозначен - компилятор не может знать, что это одно значение, оно также может быть кратным.Тем не менее, вы можете использовать простой массив с одним элементом, чтобы помочь компилятору:

#pragma omp for reduction(+:sum[:1])

Это работает с OpenMP 4.5 - который, к счастью, поддерживается компилятором Cray.Я тестировал с GCC 8.2.0

PS Предлагаемый Джимом sum[0] также, похоже, работает с GCC, но я не уверен, что с этим делать.Я не могу найти какой-либо явной ссылки на элементы массива (или элементы массива, которые включают элементы массива согласно глоссарию OpenMP) в документации по сокращению.

0 голосов
/ 14 сентября 2018
int myroutine(double *a, double *sum, int n)
{
    int i;
    static double localSum = *sum;

#pragma omp for reduction(+:localSum)
    for(i=0;i<n;i++){
        localSum += a[i];
    }
    *sum = localSum;

    return 0;
}

работает, но это ужасно и ужасно, потому что оно сломалось бы, если бы вы попробовали его из отдельных команд во вложенной параллельной области. (Хотя это безопасно, если вы не используете вложенный параллелизм и не запускаете OpenMP из независимых pthreads, что почти одно и то же!)

Я надеюсь, что что-то вроде

 #pragma omp for reduction(+:sum[0])

будет работать в OpenMP 5.0, где секции массивов поддерживаются в сокращениях, но, к сожалению, компиляторы, вероятно, еще не созданы (понятно, поскольку спецификация еще не завершена!)

...