首页 文章

C结构与CUDA内核的动态数据?

提问于
浏览
0

可以说我有一个数据结构:

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() .

思考?

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

1 回答

  • 2

    其次,cudaMemcpy()是否足够聪明,可以深入挖掘复杂数据结构的子对象?我想不是 .

    你说得对, cudaMemcpy() 不进行递归复制 . 为了实现你想要的,你应该做这样的事情:

    // Create mbd on host
    MyBigData *mbd_host, *mbd;
    mbd_host = (MyBigData *) malloc( sizeof(myBigData) );
    // Fill it with pointers to device arrays
    cudaMalloc( &mbd_host->dataArray, 10 * sizeof(float) );
    // etc for other structure fields
    // Create mbd on device
    cudaMalloc( &mbd, sizeof(MyBigData) );
    // Copy structure, filled with device addresses, to device memory
    cudaMemcpy( mbd, mbd_host, sizeof(mbd), cudaMemcpyHostToDevice );
    // Voila!
    

    顺便说一句,在 __global__ 中存储MyBigData结构可能是个好主意,但在设备的 __constant__ 内存中(你必须声明一个常量而不是用 cudaMalloc 分配 mbd 并使用 cudaMemcpyToSymbol 而不是最后 cudaMemcpy

相关问题