在GPU上填充阵列

时间:2013-04-03 16:20:20

标签: cuda

我想在GPU上填充我的阵列。为了做到这一点,我写了generateVetor函数

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();
    }
}

在main中,我为数组A动态分配内存

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

generateVector(A,numOfData);

但是功能会出现以下错误:不允许从设备调用主机功能。为什么?我得到这个错误?

3 个答案:

答案 0 :(得分:1)

您至少有3个问题:

  1. __device__表示可从GPU代码而非主机代码调用的函数。但是你是从主持人那里打电话给generateVector()的。您只需删除__device__装饰器即可解决此问题。
  2. 您使用numOfData作为要分配的数据的大小。但是所需的大小参数是 bytes 。根据您在调用numOfData时对generateVector()的使用情况,您应该使用sizeof(int)*numOfData之类的内容来分配大小。
  3. 您正在向generateVector()指针A传递,但A是指向设备内存的指针。您不能直接在主机代码中使用这些指针(除了作为API函数的参数,如cudaMalloc和cudaMemcpy)。相反,你需要做类似的事情:

    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);
    
  4. 您可能想要详细了解如何指示主机和设备功能here

    如果您确实想从设备代码(程序中的其他位置)使用generateVector(),那么您将遇到另一个问题,即来自rand()的{​​{1}}函数无法调用来自设备代码。但是,这似乎不是你的意图。

答案 1 :(得分:0)

您的generateVector函数被标记为 device 函数,但它调用rand_from_0_to_100_gen()调用rand(),它们未标记为设备函数。 GPU函数只能调用驻留在GPU上的代码,而不能调用主机上的代码。

我猜这是你的错误信息“不允许从设备功能调用主机功能”。

答案 2 :(得分: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));
}