yugr
yugr

Reputation: 21955

Illegal context for vector clause in simple OpenACC kernel

I'm trying to compile a simple OpenACC benchmark:

void foo(const float * restrict a, int a_stride, float * restrict c, int c_stride) {
#pragma acc parallel copyin(a[0:a_stride*256]) copyout(c[0:c_stride*256])
#pragma acc loop vector(128)
  {
    for (int i = 0; i < 256; ++i) {
      float sum = 0;
      for (int j = 0; j < 256; ++j) {
        sum += *(a + a_stride * i + j);
      }
      *(c + c_stride * i) = sum;
    }
  }
}

with Nvidia HPC SDK 21.5 and run into an error

$ nvc++ -S tmp.cc -Wall -Wextra -O2 -acc -acclibs -Minfo=all -g -gpu=cc80
NVC++-S-0155-Illegal context for gang(num:) or worker(num:) or vector(length:)  (tmp.cc: 7)
NVC++/x86-64 Linux 21.5-0: compilation completed with severe errors

Any idea what may cause this? From what I can tell my syntax for vector(128) is legal.

Upvotes: 0

Views: 263

Answers (1)

Mat Colgrove
Mat Colgrove

Reputation: 5646

It's illegal OpenACC syntax to use "vector(value)" with a parallel construct. You need to use a "vector_length" clause on the parallel directive to define the vector length. The reason is because "parallel" defines a single compute region to be offloaded and hence all vector loops in this region need to have the same vector length.

You can use "vector(value)" only with a "kernels" construct since the compiler can then split the region into multiple kernels each having a different vector length.

Option 1:

% cat test.c
void foo(const float * restrict a, int a_stride, float * restrict c, int c_stride) {
#pragma acc parallel vector_length(128) copyin(a[0:a_stride*256]) copyout(c[0:c_stride*256])
#pragma acc loop vector
  {
    for (int i = 0; i < 256; ++i) {
      float sum = 0;
      for (int j = 0; j < 256; ++j) {
        sum += *(a + a_stride * i + j);
      }
      *(c + c_stride * i) = sum;
    }
  }
}
% nvc -acc -c test.c -Minfo=accel
foo:
      4, Generating copyout(c[:c_stride*256]) [if not already present]
         Generating copyin(a[:a_stride*256]) [if not already present]
         Generating Tesla code
          5, #pragma acc loop vector(128) /* threadIdx.x */
          7, #pragma acc loop seq
      5, Loop is parallelizable
      7, Loop is parallelizable

Option 2:

% cat test.c
void foo(const float * restrict a, int a_stride, float * restrict c, int c_stride) {
#pragma acc kernels copyin(a[0:a_stride*256]) copyout(c[0:c_stride*256])
#pragma acc loop independent vector(128)
  {
    for (int i = 0; i < 256; ++i) {
      float sum = 0;
      for (int j = 0; j < 256; ++j) {
        sum += *(a + a_stride * i + j);
      }
      *(c + c_stride * i) = sum;
    }
  }
}
% nvc -acc -c test.c -Minfo=accel
foo:
      4, Generating copyout(c[:c_stride*256]) [if not already present]
         Generating copyin(a[:a_stride*256]) [if not already present]
      5, Loop is parallelizable
         Generating Tesla code
          5, #pragma acc loop gang, vector(128) /* blockIdx.x threadIdx.x */
          7, #pragma acc loop seq
      7, Loop is parallelizable

Upvotes: 2

Related Questions