2013-02-03 70 views
0

我想與結構類似將內核函數的參數作爲C++結構體?

struct kernel_data { 
    double *A; 
    double *B; 
    double *C; 
    const int *A_dims; 
    const int *B_dims; 
    int C_dims[2]; 
}; 

爲宗旨,我需要初始化設備,終場前cudaMalloc()給出傳遞內核函數的參數,但我怎麼能初始化。這個函數包含這些參數,我打算通過這些參數。或者我必須單獨傳遞它們?

回答

2

你可以通過拷貝內核來傳遞這個結構。 請記住,在Fermi上的前費米卡4KB上傳遞給內核的參數的總大小不得超過256B。

因此,您必須使用cudaMalloc來分配設備內存,而不是您在結構中設置指向設備內存的指針。最後,你通過拷貝將你的結構傳遞給內核。

我強烈建議您避免在C++代碼中使用此結構。取而代之的

struct kernel_data { 
    double *A; 
    double *B; 
    double *C; 
    const int *A_dims; 
    const int *B_dims; 
    int C_dims[2]; 
}; 

你應該做這樣的事情

class DeviceData{ 
public: 
    DeviceData(...){//Do cudaMalloc here} 
    ~DeviceData(...){//Do cudaFree here} 
private: 
    double *_A; 
    int _dims;  
}; 

這個類將保持設備上可用的數據,這是異常安全。 比你可以實現一個包裝,可以傳遞給內核

class DeviceDataWrapper{ 
public: 
    __host__ DeviceDataWrapper(DeviceData& device): 
     _A(device._A), 
     _dims(device._dims) 
     {} 

    __forceinline__ __device__ double* data(){return _A;} 
    __forceinline__ __device__ int dims()const{return _dims;} 

private: 
    double *_A; 
    int _dims; 
} 

,然後調用內核以這種方式

__global__ void myKernel(DeviceDataWrapper a, DeviceDataWrapper b, DeviceData2Wrapper c){ 
//do something like a.data()[0] = 1; 
} 

DeviceData A,B; 
DeviceData2 C; 
myKernel<<< >>>(A,B,C); 
+0

該結構的副本將太大,更不用說256個字節的尺寸(以及限制只適用於計算1.x能力的硬件)。 – talonmies

+0

這只是一個提醒,如果你建立的分層結構,可以經常達到限制。 –

3

通過價值結構就傳遞給內核,就像任何其他參數:

struct kernel_data args; 

cudaMalloc(&(args.A), sizeof(double)*.....); 
cudaMalloc(&(args.B), sizeof(double)*.....); 
cudaMalloc(&(args.C), sizeof(double)*.....); 
cudaMalloc(&(args.A_dims), sizeof(int)*.....); 
cudaMalloc(&(args.B_dims), sizeof(int)*.....); 

kernel<<<....>>>(args); 

有一個理論上的限制參數列表大小從256個字節到4KB,這取決於你用什麼硬件,如果你曾經超過它,複製任何東西將args結構轉換爲設備分配並將其作爲指針傳遞,或者將其複製到常量內存指針。

從主機初始化陣列,只需使用標準cudaMemcpy呼叫:

cudaMemcpy(args.A, hostA, sizeof(double)*....., cudaMemcpyHostToDevice);