2013-11-22 89 views
0

幾個月來一直在玩這個宏偉的CUDA實驗,我發現自己嘗試了更多,試圖從教程示例中脫離出來。我的問題是這樣的:如果我只想在GPU上使用陣列來做臨時存儲而不將它們複製回主機來顯示/輸出,我可以用__device__ double array[numpoints];創建一個設備陣列然後對於我想要的任何東西從GPU拿回來,我需要做整個cudaMalloc,cudaMemcpy spiel,對吧?另外,在一種方法或另一種方法之間是否有區別?我以爲他們都在全局內存中創建數組。臨時CUDA設備陣列

回答

1

請參閱this關於__device__限定符的說明。因此,如果您聲明__device__,則無法通過cudaMemcpy在主機中訪問它,但鏈接中提到了其他信息。

相反,你所能做的就是在主機代碼聲明全局指針(即,沒有__device__),並使用cudaMalloc分配。因此您可以使用將結果複製回主機。

+4

cudaMemcpy可以用來複制靜態聲明的__device__內存。這就是'cudaGetSymbolAddress'和'cudaGetSymbolSize'的用途 - 您可以在運行時獲得靜態符號的詳細信息,然後像使用其他主機地址一樣使用它們。 – talonmies

+0

@talonmies:很高興認識這個。剛剛嘗試,它的工作謝謝你。如果你願意回答相同的問題,我會贊成它(看起來這是問題的海報正在尋找的東西)。 –

1

您可以創建,填寫和使用globl存儲器陣列,而不需要使用cudaMemcpy將數據從主機進行初始化複製,如果這是你問的。在下面的簡單例子中,我創建了一個全局內存數組,它直接在設備上初始化,然後在不再需要時釋放它。

#include<stdio.h> 

__global__ void init_temp_data(float* temp_data) { 
    temp_data[threadIdx.x] = 3.f; 
} 

__global__ void copy_global_data(float* temp_data, float* d_data) { 
    d_data[threadIdx.x] = temp_data[threadIdx.x]; 
} 

#define gpuErrchk(ans) { gpuAssert((ans), __FILE__, __LINE__); } 
inline void gpuAssert(cudaError_t code, char *file, int line, bool abort=true) 
{ 
    if (code != cudaSuccess) 
    { 
     fprintf(stderr,"GPUassert: %s %s %d\n", cudaGetErrorString(code), file, line); 
     if (abort) exit(code); 
    } 
} 

int main() { 

    float* data = (float*)malloc(16*sizeof(float)); 
    float* d_data; gpuErrchk(cudaMalloc((void**)&d_data,16*sizeof(float))); 
    float* temp_data; gpuErrchk(cudaMalloc((void**)&temp_data,16*sizeof(float))); 

    init_temp_data<<<1,16>>>(temp_data); 
    gpuErrchk(cudaPeekAtLastError()); 
    gpuErrchk(cudaDeviceSynchronize()); 

    copy_global_data<<<1,16>>>(temp_data,d_data); 
    gpuErrchk(cudaPeekAtLastError()); 
    gpuErrchk(cudaDeviceSynchronize()); 

    gpuErrchk(cudaFree(temp_data)); 
    gpuErrchk(cudaMemcpy(data,d_data,16*sizeof(float),cudaMemcpyDeviceToHost)); 

    for (int i=0; i<16; i++) printf("Element number %i is equal to %f\n",i,data[i]); 

    getchar(); 

    return 0; 
}