c++ - CUDA cudaMemcpy 数组结构

标签 c++ c arrays struct cuda

我想在我的项目中清理 CUDA 内核的参数。


现在,内核需要 3 个 uint32_t 数组,这导致代码非常难看:(id 表示全局线程 ID,valX 是某个任意值)

__global__ void some_kernel(uint32_t * arr1, uint32_t * arr2, uint32_t * arr3){arr1[id] = val1; arr2[id] = val2; arr3[id] = val3;}

我想用一个结构包围所有这些数组:

typedef struct S{uint_32_t arr1, uint_32_t arr2, uint_32_t arr3, uint32_t size} S;

其中 size 表示结构中每个 arrX 的长度。

我想要的是:

__global__ void some_kernel(S * s){s->arr1[id] = val1; s->arr2[id] = val2; s->arr3[id] = val3;}

对于这样的结构,相应的 cudaMalloc 和 cudaMemcpy 会是什么样子? 这是否存在任何我尚未发现的性能缺陷?

提前致谢!

最佳答案

您至少有两个选择。一个很好的选择是 already given由 talonmies,但我将向您介绍“艰苦学习”的方法。

首先,你的结构定义:

typedef struct S {
    uint32_t *arr1;
    uint32_t *arr2;
    uint32_t *arr3; 
    uint32_t size;
} S;

...和内核定义(带有一些全局变量,但您不需要遵循该模式):

const int size = 10000;

__global__ void some_kernel(S *s)
{
    int id = blockIdx.x * blockDim.x + threadIdx.x;
    if (id < size)
    {
        s->arr1[id] = 1; // val1
        s->arr2[id] = 2; // val2
        s->arr3[id] = 3; // val3
    }
}

请注意,if 可防止您越界。

接下来,我们提供了一些函数来准备数据、执行内核并打印一些结果。第一部分是数据分配:

uint32_t *host_arr1, *host_arr2, *host_arr3;
uint32_t *dev_arr1, *dev_arr2, *dev_arr3;

// Allocate and fill host data
host_arr1 = new uint32_t[size]();
host_arr2 = new uint32_t[size]();
host_arr3 = new uint32_t[size]();

// Allocate device data   
cudaMalloc((void **) &dev_arr1, size * sizeof(*dev_arr1));
cudaMalloc((void **) &dev_arr2, size * sizeof(*dev_arr2));
cudaMalloc((void **) &dev_arr3, size * sizeof(*dev_arr3));

// Allocate helper struct on the device
S *dev_s;
cudaMalloc((void **) &dev_s, sizeof(*dev_s));

没什么特别的,你只是分配三个数组和结构。看起来更有趣的是如何处理将此类数据复制到设备中:

// Copy data from host to device
cudaMemcpy(dev_arr1, host_arr1, size * sizeof(*dev_arr1), cudaMemcpyHostToDevice);
cudaMemcpy(dev_arr2, host_arr2, size * sizeof(*dev_arr2), cudaMemcpyHostToDevice);
cudaMemcpy(dev_arr3, host_arr3, size * sizeof(*dev_arr3), cudaMemcpyHostToDevice);

// NOTE: Binding pointers with dev_s
cudaMemcpy(&(dev_s->arr1), &dev_arr1, sizeof(dev_s->arr1), cudaMemcpyHostToDevice);
cudaMemcpy(&(dev_s->arr2), &dev_arr2, sizeof(dev_s->arr2), cudaMemcpyHostToDevice);
cudaMemcpy(&(dev_s->arr3), &dev_arr3, sizeof(dev_s->arr3), cudaMemcpyHostToDevice);

除了您注意到的数组的普通拷贝外,还需要将它们与结构“绑定(bind)”。为此,您需要传递一个指针地址。结果,只有这些指针被复制。

下一次内核调用,再次将数据复制回主机并打印结果:

// Call kernel
some_kernel<<<10000/256 + 1, 256>>>(dev_s); // block size need to be a multiply of 256

// Copy result to host:
cudaMemcpy(host_arr1, dev_arr1, size * sizeof(*host_arr1), cudaMemcpyDeviceToHost);
cudaMemcpy(host_arr2, dev_arr2, size * sizeof(*host_arr2), cudaMemcpyDeviceToHost);
cudaMemcpy(host_arr3, dev_arr3, size * sizeof(*host_arr3), cudaMemcpyDeviceToHost);

// Print some result
std::cout << host_arr1[size-1] << std::endl;
std::cout << host_arr2[size-1] << std::endl;
std::cout << host_arr3[size-1] << std::endl;

请记住,在任何严肃的代码中,您都应该始终检查来自 CUDA API 调用的错误。

关于c++ - CUDA cudaMemcpy 数组结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31598021/

相关文章:

c++ - Qt - 首选使用什么 - 小部件或 View ? (树、表、列表)

临时地址的 C++ 地址不会导致构建错误

c - "++"运算符在 "char *"上做了什么?

c++ - C和C++中引用传递的含义?

java - 变量 "j"无法解析为变量 - 二维数组

c++ - 如何遍历字符串中的单词?

c++ - 如何理解已释放 block 的损坏中缀模式

c - 理解 C 中函数的 typedef

java - 如何使用java查找给定序列数组列表中的缺失元素?

c++ - 追逐指针的方法失败