2012-01-25 54 views
11

我需要以下 主機代碼的設備版本:設備函數指針

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; 
} 
+0

函數指針在設備代碼中是不支持的。 – Yappie

+0

@Yappie:這是錯誤的 - Fermi支持函數指針 – talonmies

+0

CUDA SDK中有一個函數指針示例,您可以看到一個與您的問題非常相似的示例[在CUDA開發人員論壇的這篇文章中](http://forums.nvidia.com/index.php?showtopic=156792&view=findpost&p=1201985)。 – talonmies

回答

19

函數指針是允許在費米。 這是你如何做到的:

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; 
} 
+0

非常感謝你!你的回答對我來說非常有用。是否可以動態分配數組func_list? – micheletuttafesta

+0

我編輯了代碼來說明如何使用動態分配。 – brano

+0

brano我非常感謝您的幫助!但是,我發現這個工作解決方案...是否正確?我必須在內核中完成「func_list_d」的分配 – micheletuttafesta