【问题标题】:device function pointers设备功能指针
【发布时间】:2012-02-18 11:59:47
【问题描述】:

我需要以下设备版本 主机代码:

double (**func)(double x);

double func1(double x)
{
 return x+1.;
}

double func2(double x)
{
 return x+2.;
}

double func3(double x)
{
 return x+3.;
}

void test(void)
{
 double x;

 for(int i=0;i<3;++i){
  x=func[i](2.0);
  printf("%g\n",x);
 }

}

int main(void)
{
 func=(double (**)(double))malloc(10*sizeof(double (*)(double)));

 test();

 return 0;
}

其中 func1、func2、func3 必须是 __device__ 功能 和“测试” 必须是(适当修改的)__global__ 内核。

我有一个 NVIDIA GeForce GTS 450(计算能力 2.1) 先感谢您 米歇尔

================================================ =========

一个可行的解决方案

#define REAL double

typedef REAL (*func)(REAL x);

__host__ __device__ REAL func1(REAL x)
{
    return x+1.0f;
}

__host__ __device__ REAL func2(REAL x)
{
    return x+2.0f;
}

__host__ __device__ REAL func3(REAL x)
{
    return x+3.0f;
}

__device__ func func_list_d[3];
func func_list_h[3];

__global__ void assign_kernel(void)
{
    func_list_d[0]=func1;
    func_list_d[1]=func2;
    func_list_d[2]=func3;
}

void assign(void)
{
    func_list_h[0]=func1;
    func_list_h[1]=func2;
    func_list_h[2]=func3;
}


__global__ void test_kernel(void)
{
    REAL x;
    for(int i=0;i<3;++i){
        x=func_list_d[i](2.0);
        printf("%g\n",x);
  }
}

void test(void)
{
    REAL x;
    printf("=============\n");
    for(int i=0;i<3;++i){
        x=func_list_h[i](2.0);
        printf("%g\n",x);
  }
}

int main(void)
{
    assign_kernel<<<1,1>>>();
    test_kernel<<<1,1>>>();
    cudaThreadSynchronize();

    assign();
    test();

    return 0;
}

【问题讨论】:

  • 设备代码不支持函数指针。
  • @Yappie:这是错误的——Fermi 支持函数指针
  • CUDA SDK 中有一个函数指针示例,您可以看到一个与您的问题in this post on the CUDA developer forums 非常相似的示例。

标签: cuda


【解决方案1】:

Fermi 上允许使用函数指针。 你可以这样做:

typedef double (*func)(double x);

__device__ double func1(double x)
{
return x+1.0f;
}

__device__ double func2(double x)
{
return x+2.0f;
}

__device__ double func3(double x)
{
return x+3.0f;
}

__device__ func pfunc1 = func1;
__device__ func pfunc2 = func2;
__device__ func pfunc3 = func3;

__global__ void test_kernel(func* f, int n)
{
  double x;

  for(int i=0;i<n;++i){
   x=f[i](2.0);
   printf("%g\n",x);
  }
}

int main(void)
{
  int N = 5;
  func* h_f;
  func* d_f;
  h_f = (func*)malloc(N*sizeof(func));
  cudaMalloc((void**)&d_f,N*sizeof(func));

  cudaMemcpyFromSymbol( &h_f[0], pfunc1, sizeof(func));
  cudaMemcpyFromSymbol( &h_f[1], pfunc1, sizeof(func));
  cudaMemcpyFromSymbol( &h_f[2], pfunc2, sizeof(func));
  cudaMemcpyFromSymbol( &h_f[3], pfunc3, sizeof(func));
  cudaMemcpyFromSymbol( &h_f[4], pfunc3, sizeof(func));

  cudaMemcpy(d_f,h_f,N*sizeof(func),cudaMemcpyHostToDevice);

  test_kernel<<<1,1>>>(d_f,N);

  cudaFree(d_f);
  free(h_f);

  return 0;
}

【讨论】:

  • 非常感谢!!你的回答对我很有用。是否可以动态分配数组 func_list ?
  • 我已经编辑了代码来说明如何使用动态分配。
  • brano 我非常感谢您的帮助!!但是我找到了这个可行的解决方案......它是否正确?我必须在内核中分配“func_list_d”
  • 上面的例子有效。如果您想在内核中分配 d_f ,则可以这样做。只需删除所有 cudaMemcpyFromSymbol 并启动一个内核,而不是写入 d_f 并使用 pfunc1、pfunc2、pfunc3。
  • 好的,布拉诺!你的代码将成为我未来工作中的宝藏
猜你喜欢
  • 2013-05-24
  • 1970-01-01
  • 2013-01-05
  • 1970-01-01
  • 1970-01-01
  • 2013-05-20
  • 1970-01-01
  • 1970-01-01
  • 2011-07-18
相关资源
最近更新 更多