我想在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);
但是功能会出现以下错误:不允许从设备调用主机功能。为什么?我得到这个错误?
答案 0 :(得分:1)
您至少有3个问题:
__device__
表示可从GPU代码而非主机代码调用的函数。但是你是从主持人那里打电话给generateVector()
的。您只需删除__device__
装饰器即可解决此问题。numOfData
作为要分配的数据的大小。但是所需的大小参数是 bytes 。根据您在调用numOfData
时对generateVector()
的使用情况,您应该使用sizeof(int)*numOfData
之类的内容来分配大小。您正在向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);
您可能想要详细了解如何指示主机和设备功能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));
}