2013-04-03 81 views
0

我想在GPU上填充陣列。爲了做到這一點,我寫generateVetor功能在GPU上填充陣列

int rand_from_0_to_100_gen(void) { 
    return rand() % 100; 
} 

__device__ void generateVector(int * hData,int count) { 

    for (int i = 0; i < count; i++) { 
     hData[i] = rand_from_0_to_100_gen(); 
    } 
} 

在主我動態分配內存數組A

int *A = NULL; 
err = cudaMalloc((void **) &A, numOfData); 

generateVector(A,numOfData); 

但功能給出​​了錯誤:從設備調用主機功能是不允許。爲什麼?我得到這個錯誤?

回答

1

您至少有3個問題:

  1. __device__表示該功能是由GPU代碼調用不是主代碼。但是你從主機呼叫generateVector()。你可以簡單地通過刪除__device__修飾器來解決這個問題。
  2. 您正在使用numOfData作爲要分配的數據大小。但所需的大小參數在字節。根據您在致電generateVector()時對numOfData的使用情況,您應該使用類似sizeof(int)*numOfData這樣的分配大小。
  3. 您傳遞給generateVector()指針A,但A是指向設備內存的指針。您不能直接在主機代碼中使用這些指針(除了作爲諸如cudaMalloc和cudaMemcpy之類的API函數的參數之外)。相反,你需要做的是這樣的:

    int *A = NULL; 
    int *h_A = NULL; 
    h_A = (int *)malloc(numOfData*sizeof(int)); 
    generateVector(h_A, numOfData); 
    cudaMemcpy(A, h_A, numOfData*sizeof(int), cudaMemcpyHostToDevice); 
    

你可能想了解更多關於如何指示主機和設備功能here

如果你真的不想使用generateVector()從設備代碼(在程序中其他地方),那麼你將有一個附加的問題,從stdlib.hrand()功能是無法從設備代碼調用。但是,這似乎不是你的意圖。

+0

的問題是:我不想從主機設備複製。我直接在GPU上填充我的陣列。我必須從CPU複製嗎?這是限制嗎? – user2240256

+0

您無法直接從主機代碼寫入GPU(設備)內存。您必須使用類似'cudaMemcpy'或'cudaMemset'的API調用。或者,你可以從GPU端啓動一個內核,並讓它做任何你想做的事情。但是你發佈的代碼是主機代碼(主要是),並且不包含任何內核啓動。 –

0

您的generateVector函數被標記爲設備函數,但它調用rand_from_0_to_100_gen(),它調用rand(),它們未被標記爲設備函數。 GPU功能只能調用駐留在GPU上的代碼,而不能在主機上調用。

我的猜測是這是你的錯誤信息「從設備函數調用主機函數是不允許的」指的是。

0

這裏是做你想要做什麼,即使它可能不是最優的代碼:

// Compiled using nvcc main.cu -arch=sm_21 -o main && ./main 
// See document http://www.cs.cmu.edu/afs/cs/academic/class/15668-s11/www/cuda-doc/CURAND_Library.pdf 
// And http://aresio.blogspot.fr/2011/05/cuda-random-numbers-inside-kernels.html 
#include <stdio.h> 
#include <cuda.h> 
#include <curand_kernel.h> 
#include <curand.h> 

#define cuda_DBG(x) if(x!=cudaSuccess) {\ 
     printf("error at %s:%u\n", __FILE__, __LINE__);\ 
     return -1;\ 
     } 

__global__ void setup_kernel(curandState *state, unsigned long seed) { 
    int id = threadIdx.x; 
    curand_init(seed, id, 0, &state[id]); 
} 

__global__ void generateVector(int *hData, curandState *globalState) { 
    size_t i = blockIdx.x; 
    float RANDOM = 100*curand_uniform(&globalState[i]); 
    hData[i] = (int)RANDOM; 
    if(i==50) printf("hData[50]=%u (RANDOM=%f)\n", hData[i], RANDOM); 
} 

int main() { 
    int *A = NULL, numOfData=1000; 
    curandState *devState; 
    cuda_DBG(cudaMalloc((void **) &A, sizeof(int)*numOfData)); 
    cuda_DBG(cudaMalloc((void **) &devState, sizeof(devState)*numOfData)); 

    setup_kernel<<<numOfData, 1>>>(devState, time(NULL)); 
    generateVector<<<numOfData, 1>>>(A, devState); 

    cuda_DBG(cudaFree(A)); 
    cuda_DBG(cudaFree(devState)); 
}