假设我有一个数据结构:
struct MyBigData {
float * dataArray;
float * targetArray;
float * nodes;
float * dataDataData;
}
我希望能够在一些不同的 CUDA 内核周围传递这个结构。我不想将多个数组作为参数传递,所以我可以只传递结构并完成它吗?我知道内核支持 C 结构,但是 C 结构中的动态内存呢?
看来我只是为了在 CUDA 卡上制作结构:
MyBigData * mbd = (MyBigData *) cudaMalloc( sizeof(MyBigData) );
但是结构中数组的动态内存呢?下面的这一行编译但有一个运行时错误:
mbd->dataArray = (float *) cudaMalloc( 10 * sizeof(float) );
这是因为 cudaMalloc() 在 CPU 上运行,它无法读取 mdb->dataArray 来设置指针等于新的内存地址。所以存在运行时错误。但是,这可以编译并运行,但似乎不是我想要的:
MyBigData * mbd = (MyBigData *) malloc( sizeof(myBigData) );
mbd->dataArray = (float *) cudaMalloc( 10 * sizeof(float) );
因为现在,虽然这是有效的,但现在 mbd 驻留在主系统内存上,并且浮点指针指向在 CUDA 设备上分配的内存。所以我不能只传递一个指向 MyBigData 结构的指针,我必须将结构中的每个变量单独传递给内核。不干净。我想要的是:
someKernel<<<1,1>>>(mbd);
不是:
someKernel<<<1,1>>>(mbd->dataArray, mbd->targetArray, mbd->nodes, mbd->dataDataData);
所以我在想,cudaMemcpy() 怎么样?我在想这个:
MyBigData *d_mbd = cudaMemcpy( (void*) &d_mbd, (void*) mbd, SOMESIZE, CudaHostToDevice);
但是那我应该为 SOMESIZE 放什么呢?我不能使用 sizeof(MyBigData),因为这将包括浮点指针的大小,而不是数组的实际大小。其次,cudaMemcpy() 是否足够聪明,可以深入挖掘复杂数据结构的子对象?我想不是。
那么,CUDA卡上不可能有包含动态内存的结构吗?或者我错过了什么。简单的方法是让 CUDA 内核分配一些内存,但不能从 CUDA 内核调用 cudaMalloc()。
想法?
5 月 7 日更新:我编写了这段代码,它可以编译,但它告诉我所有值都为零。我认为我正在正确地创建对象并使用 CUDA 内核正确填充值。这些值只是线程 ID。我怀疑我没有正确打印这些值。想法?谢谢!
MyBigData* generateData(const int size) {
MyBigData *mbd_host, *mbd_cuda;
mbd_host = (MyBigData *) malloc( sizeof(MyBigData) );
cudaMalloc( (void**) &mbd_host->dataArray, size * sizeof(float) );
cudaMalloc( (void**) &mbd_host->targetArray, size * sizeof(float) );
cudaMalloc( (void**) &mbd_host->nodes, size * sizeof(float) );
cudaMalloc( (void**) &mbd_host->dataDataData, size * sizeof(float) );
cudaMalloc( (void**) &mbd_cuda, sizeof(MyBigData) );
cudaMemcpy( mbd_cuda, mbd_host, sizeof(mbd_host), cudaMemcpyHostToDevice );
free(mbd_host);
return mbd_cuda;
}
void printCudaData(MyBigData* mbd_cuda, const int size) {
MyBigData *mbd;
cudaMemcpy( mbd, mbd_cuda, sizeof(mbd_cuda), cudaMemcpyDeviceToHost);
MyBigData *mbd_host = (MyBigData *) malloc( sizeof(MyBigData));
mbd_host->dataArray = (float*) malloc(size * sizeof(float));
mbd_host->targetArray = (float*) malloc(size * sizeof(float));
mbd_host->nodes = (float*) malloc(size * sizeof(float));
mbd_host->dataDataData = (float*) malloc(size * sizeof(float));
cudaMemcpy( mbd_host->dataArray, mbd->dataArray, size * sizeof(float), cudaMemcpyDeviceToHost);
cudaMemcpy( mbd_host->targetArray, mbd->targetArray, size * sizeof(float), cudaMemcpyDeviceToHost);
cudaMemcpy( mbd_host->nodes, mbd->nodes, size * sizeof(float), cudaMemcpyDeviceToHost);
cudaMemcpy( mbd_host->dataDataData, mbd->dataDataData, size * sizeof(float), cudaMemcpyDeviceToHost);
for(int i = 0; i < size; i++) {
printf("data[%i] = %f\n", i, mbd_host->dataArray[i]);
printf("target[%i] = %f\n", i, mbd_host->targetArray[i]);
printf("nodes[%i] = %f\n", i, mbd_host->nodes[i]);
printf("data2[%i] = %f\n", i, mbd_host->dataDataData[i]);
}
free(mbd_host->dataArray);
free(mbd_host->targetArray);
free(mbd_host->nodes);
free(mbd_host->dataDataData);
free(mbd_host);
}
这是我的内核和调用它的函数:
__global__ void cudaInitData(MyBigData* mbd) {
const int threadID = threadIdx.x;
mbd->dataArray[threadID] = threadID;
mbd->targetArray[threadID] = threadID;
mbd->nodes[threadID] = threadID;
mbd->dataDataData[threadID] = threadID;
}
void initData(MyBigData* mbd, const int size) {
if (mbd == NULL)
mbd = generateData(size);
cudaInitData<<<size,1>>>(mbd);
}
我的main()
电话:
MyBigData* mbd = NULL;
initData(mbd, 10);
printCudaData(mbd, 10);