ошибка openacc при присвоении значений динамически выделяемому массиву элементов структуры структуры, на которую ссылается указатель

Я пытаюсь обдумать объединение openacc с указателями на структуры, содержащие динамически распределяемые элементы. Код ниже не работает с

Сбой в потоке:1 вызов cuStreamSynchronize возвратил ошибку 700: недопустимый адрес во время выполнения ядра

при компиляции с использованием nvc («64-разрядная цель nvc 20.9-0 LLVM на x86-64 Linux -tp haswell»). Насколько я могу судить, я следую подходу, предложенному, например, в руководстве по началу работы с OpenACC. Но почему-то предположительно указатели не прилипают (?) к устройству. Кто-нибудь знает, что здесь не так?

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

typedef struct grid
{
  int N;
  double *X;
} grid;

void allocate(grid* g, int N)
{
  g->N = N;
  g->X = (double*) malloc(sizeof(double) * g->N);

  #pragma acc enter data create(g[0:1])
  #pragma acc enter data create(g->X[0:N])
}

void release(grid* g)
{
  #pragma acc exit data delete(g->X[0:g->N])
  #pragma acc exit data delete(g[0:1])

  free(g->X);
}

void fill(grid * g)
{
  int i;

  #pragma acc parallel loop
  for (i = 0; i < g->N; i++)
  {
    g->X[i] = 42; // the cuprit, commenting this removes the error too
  }
}

int main()
{
  grid g;

  allocate(&g, 10);

  fill(&g);

  release(&g);

  return 0;
}```

1 ответ

Из сообщений обратной связи компилятора вы увидите что-то вроде:

           fill:
          32, Accelerator restriction: size of the GPU copy of g is unknown
              Generating Tesla code
              32, #pragma acc loop gang, vector(128) /* blockIdx.x threadIdx.x */
          32, Generating implicit copyin(g) [if not already present]
          37, Generating update self(g->X[:g->N])

Проблема в том, что компилятор не может неявно копировать агрегатные типы с элементами динамических данных, поэтому вам нужно добавить «представление (g)», чтобы указать, что g уже является устройством.

Кроме того, вы захотите скопировать, чтобы получить значение N на устройстве, и вам не нужно включать форму массива в директиву удаления выходных данных. Например:

      % cat test.c
#include <stdlib.h>
#include <stdio.h>

typedef struct grid
{
  int N;
  double *X;
} grid;

void allocate(grid* g, int N)
{
  g->N = N;
  g->X = (double*) malloc(sizeof(double) * g->N);

  #pragma acc enter data copyin(g[0:1])
  #pragma acc enter data create(g->X[0:N])
}

void release(grid* g)
{
  #pragma acc exit data delete(g->X)
  #pragma acc exit data delete(g)

  free(g->X);
}

void fill(grid * g)
{
  int i;

  #pragma acc parallel loop present(g)
  for (i = 0; i < g->N; i++)
  {
    g->X[i] = 42; // the cuprit, commenting this removes the error too
  }
  #pragma acc update self(g->X[:g->N])
  for (i = 0; i < 4; i++)
  {
    printf("%d : %f \n",i,g->X[i]);
  }
}

int main()
{
  grid g;

  allocate(&g, 10);

  fill(&g);

  release(&g);

  return 0;
}

% nvc -acc test.c -Minfo=accel -V20.9 ; a.out
allocate:
     17, Generating enter data copyin(g[:1])
         Generating enter data create(g->X[:N])
release:
     24, Generating exit data delete(g[:1],g->X[:1])
fill:
     32, Generating present(g[:1])
         Generating Tesla code
         32, #pragma acc loop gang, vector(128) /* blockIdx.x threadIdx.x */
     37, Generating update self(g->X[:g->N])
0 : 42.000000
1 : 42.000000
2 : 42.000000
3 : 42.000000
Другие вопросы по тегам