Thrust:访问用cudaMallocPitch创建的设备变量

Thrust: Accessing a device variable created with cudaMallocPitch

本文关键字:变量 创建 cudaMallocPitch 访问 Thrust      更新时间:2023-10-16

我有一个数据矩阵,我应该使用GPU(尽可能使用推力库)对其进行一些详细说明。到目前为止,我能够将数据复制到GPU并编写自己的内核函数。现在,根据我的内核函数的输出,我将利用推力库对同一数据矩阵进行其他阐述,尽可能避免从GPU<->下载和重新上传数据CPU。

因此,我使用cudaMallocPitch函数在GPU中创建了一个设备变量:

float *d_M;
size_t pitch;
cudaStatus = cudaMallocPitch(&d_M, &pitch, sizeof(float)*(N), M+1);
if (cudaStatus != cudaSuccess)
{
fprintf(stderr, "cudaMalloc Failed!");
INFO;
return CUDA_MALLOC_ERROR;
}

该变量表示一个维数为NxM+1的矩阵。在使用ad-hoc cuda函数对GPU进行了一些详细说明后,我将使用推力库对每行的元素求和,并将结果放在每行的M+1列上。

对于这种操作,我会使用推力库。我的意图应该是检索使用cudaMallocPitch创建的原始指针,将其转换为推力::device_ptr然后使用推力函数对其进行操作。所以,在代码中:

thrust::device_ptr<float> dd_M = thrust::device_pointer_cast(d_M);

但是,当我试图打印两个变量的地址以确保指针具有相同的地址时:

printf("Address d_M: %pn", &d_M);
printf("Address dd_M: %pn", &dd_M);

我得到了不同的地址值。我不知道我做错了什么。对于这样的操作,我刚刚在链接推力-内存管理功能中遵循了推力手册。

cudaMallocPitch将基本上无法使用推力。这是因为它创建了这样的分配:

D D D D D D D D D D D D D D X X
D D D D D D D D D D D D D D X X
D D D D D D D D D D D D D D X X
D D D D D D D D D D D D D D X X
D D D D D D D D D D D D D D X X
...

其中D项表示实际数据,X项表示附加到每行的额外空间,以使数据宽度与所需的机器间距相匹配。

问题是,推力对X表示的"未使用"区域没有概念。当数据中有"未使用"的间隙时,没有方便的方法来告诉推力函数分配线程(并生成适当的连续索引)。因此,如果我们将以上内容转换为推力向量:

D D D D D D D D D D D D D D X X D D D D D D D D D D D D D D X X D D ...

分散在矢量中的CCD_ 5区域在推力算法和索引中不能方便地"跳过"。如果你真的想这样做,也许可以想出一个解决上述映射的thrust::permutation_iterator,但它本身的效率低下,这将超过对倾斜数据进行操作带来的任何性能优势。

如果您使用cudaMalloc,那么您的数据将是连续的,正如推力所期望的那样。