OpenACC:从OpenACC并行循环调用cuda__设备__内核

OpenACC:从OpenACC并行循环调用cuda__设备__内核,cuda,interop,gpu,openacc,Cuda,Interop,Gpu,Openacc,如果我在hello.cu文件中有简单的测试cuda内核,如下所示: extern "C" __device__ float radians( float f ){ return f*3.14159265; } 并在mainacc.c中测试OpenACC代码: #include <stdio.h> #include <stdlib.h> #define N 10 #pragma acc routine seq extern float radians( flo

如果我在hello.cu文件中有简单的测试cuda内核,如下所示:

extern "C" __device__ float radians( float f ){
    return f*3.14159265;
}
并在mainacc.c中测试OpenACC代码:

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

#define N 10

#pragma acc routine seq
extern float radians( float );

int main() {

   int i;
   float *hptr, *dptr;
   hptr = (float *) calloc(N, sizeof(float));

   #pragma acc parallel loop copy(hptr[0:N])
   for(i=0; i<N; i++) {
       hptr[i] = radians(i*0.1f);
   }

   for( i=0; i< N; i++)
       printf("\n %dth value : %f", i, hptr[i]);
   return 0;
}
我使用“-relocatable device code true”选项等尝试了nvcc,但没有成功。加载的模块包括:

craype-accel-nvidia35
cudatoolkit/6.5
PrgEnv-cray/5.2.40

你能告诉我在OpenACC中使用cuda设备内核的正确方法吗?

我已经能够使用PGI进行这种混合,但是我还不能生成一个与Cray编译器一起工作的示例。下面是一个适用于PGI的简单示例

这是包含CUDA的文件

// saxpy_cuda_device.cu
extern "C"
__device__
float saxpy_dev(float a, float x, float y)
{
  return a * x + y;
}
这是包含OpenACC的文件

// openacc_cuda_device.cpp
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#pragma acc routine seq
extern "C" float saxpy_dev(float, float, float);

int main(int argc, char **argv)
{
  float *x, *y, tmp;
  int n = 1<<20, i;

  x = (float*)malloc(n*sizeof(float));
  y = (float*)malloc(n*sizeof(float));

  #pragma acc data create(x[0:n]) copyout(y[0:n])
  {
    #pragma acc kernels
    {
      for( i = 0; i < n; i++)
      {
        x[i] = 1.0f;
        y[i] = 0.0f;
      }
    }

    #pragma acc parallel loop
    for( i = 0; i < n; i++ )
    {
      y[i] = saxpy_dev(2.0, x[i], y[i]);
    }
  }

  fprintf(stdout, "y[0] = %f\n",y[0]);
  return 0;
}

您可以使用-Wc命令行选项将生成的ptx文件添加到CUDA链接行。我打开了一个bug,以确保我们记录了如何执行此操作

nvcc hello.cu -ptx -arch=sm_35
cc -hacc -hlist=a mainacc.c -Wc,hello.ptx

一个建议是提供子例程的主机和设备版本,然后使用“bind”子句指示从计算区域调用哪个版本。这将允许您保持主机代码的可移植性

例如:

% cat radians.cu
extern "C" __device__ float cuda_radians( float f ){
    return f*3.14159265;
}

extern "C" float radians( float f ){
    return f*3.14159265;
}
% cat test.c
#include <stdio.h>
#include <stdlib.h>

#define N 10

#pragma acc routine (radians) bind(cuda_radians) seq
extern float radians( float f);

int main() {

   int i;
   float *hptr, *dptr;
   hptr = (float *) calloc(N, sizeof(float));

   #pragma acc parallel loop copy(hptr[0:N])
   for(i=0; i<N; i++) {
       hptr[i] = radians(i*0.1f);
   }

   for( i=0; i< N; i++)
       printf("\n %dth value : %f", i, hptr[i]);
   return 0;
}
% nvcc -c radians.cu --relocatable-device-code true
% pgcc -acc -ta=tesla:cuda7.0 -Minfo=accel test.c radians.o -V15.7 -Mcuda
test.c:
main:
     15, Generating copy(hptr[:10])
         Accelerator kernel generated
         Generating Tesla code
         16, #pragma acc loop gang, vector(128) /* blockIdx.x threadIdx.x */
% a.out

 0th value : 0.000000
 1th value : 0.314159
 2th value : 0.628319
 3th value : 0.942478
 4th value : 1.256637
 5th value : 1.570796
 6th value : 1.884956
 7th value : 2.199115
 8th value : 2.513274
 9th value : 2.827434
%cat radians.cu
外部“C”\uuuuu设备\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu弧度浮动(浮动f){
返回f*3.14159265;
}
外部“C”浮动弧度(浮动f){
返回f*3.14159265;
}
%cat测试c
#包括
#包括
#定义n10
#pragma acc例程(弧度)绑定(cuda_弧度)seq
外部浮动弧度(浮动f);
int main(){
int i;
浮动*hptr,*dptr;
hptr=(float*)calloc(N,sizeof(float));
#pragma acc并行循环复制(hptr[0:N])

对于(i=0;ithanks Jeff!您是否认识Nvidia和/或Cray的任何人,他们在使用Cray toolchain时可以帮助确定链接问题或解决方法?或者这将在Cray上起作用?我假设“原则上”"这应该行得通,但也理解内部实现的复杂性。我已经用我的示例代码联系了Cray,看看他们是否有任何建议可以让它工作,但我还没有得到回复。在我看来,这像是一个名称混乱的问题。我本希望使用extern C可以防止这种情况,但没有。如果我得到他们的回复,我会发布最新消息。谢谢你追踪大卫。
nvcc hello.cu -ptx -arch=sm_35
cc -hacc -hlist=a mainacc.c -Wc,hello.ptx
% cat radians.cu
extern "C" __device__ float cuda_radians( float f ){
    return f*3.14159265;
}

extern "C" float radians( float f ){
    return f*3.14159265;
}
% cat test.c
#include <stdio.h>
#include <stdlib.h>

#define N 10

#pragma acc routine (radians) bind(cuda_radians) seq
extern float radians( float f);

int main() {

   int i;
   float *hptr, *dptr;
   hptr = (float *) calloc(N, sizeof(float));

   #pragma acc parallel loop copy(hptr[0:N])
   for(i=0; i<N; i++) {
       hptr[i] = radians(i*0.1f);
   }

   for( i=0; i< N; i++)
       printf("\n %dth value : %f", i, hptr[i]);
   return 0;
}
% nvcc -c radians.cu --relocatable-device-code true
% pgcc -acc -ta=tesla:cuda7.0 -Minfo=accel test.c radians.o -V15.7 -Mcuda
test.c:
main:
     15, Generating copy(hptr[:10])
         Accelerator kernel generated
         Generating Tesla code
         16, #pragma acc loop gang, vector(128) /* blockIdx.x threadIdx.x */
% a.out

 0th value : 0.000000
 1th value : 0.314159
 2th value : 0.628319
 3th value : 0.942478
 4th value : 1.256637
 5th value : 1.570796
 6th value : 1.884956
 7th value : 2.199115
 8th value : 2.513274
 9th value : 2.827434