0

我想在 GPU 上填充我的数组。为了做到这一点,我编写了 generateVector 函数

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

但是函数给出的错误是:不允许从设备调用主机函数。为什么?我得到这个错误是什么?

4

3 回答 3

1

你至少有3个问题:

  1. __device__表示可从 GPU 代码而非主机代码调用的函数。但是你是generateVector()从主人那里打电话来的。您可以通过删除__device__装饰器来解决此问题。
  2. 您正在使用numOfData作为要分配的数据的大小。但所需的大小参数以字节为单位。根据您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);
    

您可能想在此处阅读有关如何指示主机和设备功能的更多信息。

如果您确实想generateVector()从设备代码(程序中的其他位置)使用,那么您将遇到一个额外的问题,即无法从设备代码调用rand()函数 from 。stdlib.h但是,这似乎不是您的意图。

于 2013-04-03T16:29:59.327 回答
0

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

我的猜测是这就是您的错误消息“不允许从设备函数调用主机函数”所指的内容。

于 2013-04-03T16:35:35.877 回答
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));
}
于 2013-04-03T21:48:40.937 回答