[英]CUDA Zeropadding 3D matrix
我有一个大小为 100x200x800 的 integer 矩阵,它以平面 100*200*800 向量的形式存储在主机上,即,我有
int* h_data = (int*)malloc(sizeof(int)*100*200*800);
在设备 (GPU) 上,我想用零填充每个维度,以便获得大小为 128x256x1024 的矩阵,分配如下:
int *d_data;
cudaMalloc((void**)&d_data, sizeof(int)*128*256*1024);
获得零填充矩阵的最佳方法是什么? 我有两个想法:
cudaMemcpy
调用,因此可能非常慢有没有类似MATLAB的三维矩阵索引的可能? 在 MATLAB 中,我可以简单地执行以下操作:
h_data = rand(100, 200, 800);
d_data = zeros(128, 256, 1024);
d_data(1:100, 1:200, 1:800) = h_data;
或者,如果我使用cudaMemcpy(d_data, h_data, sizeof(int)*100*200*800, cudaMemcpyHostToDevice);
, 是否可以就地重新排序数据,这样我就不必为第二个矩阵分配 memory ,可能使用cudaMemcpy3D
或cudaMemset3D
?
正如您假设的那样,您可以使用cudaMemcpy3D
进行此操作。 基本上:
cudaMemset
将其cudaMemset
cudaMemcpy3D
为选定的子阵列执行从主机到设备的线性内存复制,从主机源到设备目标阵列。 cudaMemcpy3D
API 有点巴洛克式的、神秘的文档,并且有一些适合初学者的常见陷阱。 基本上,线性内存传输需要一个指向源和目标的倾斜指针,以及一个表示传输大小的范围。 令人困惑的部分是参数含义的变化取决于源和/或目标内存是 CUDA 数组还是倾斜线性内存。 在代码中,你会想要这样的东西:
int hw = 100, hh = 200, hd = 800;
size_t hpitch = hw * sizeof(int);
int* h_data = (int*)malloc(hpitch * hh * hd);
int dw = 128, dh = 256, dd = 1024;
size_t dpitch = dw * sizeof(int);
int *d_data;
cudaMalloc((void**)&d_data, dpitch * dh * dd);
cudaMemset(d_data, 0, dpitch * dh * dd);
cudaPitchedPtr src = make_cudaPitchedPtr(h_data, hpitch, hw, hh);
cudaPitchedPtr dst = make_cudaPitchedPtr(d_data, dpitch, dw, dh);
cudaExtent copyext = make_cudaExtent(hpitch, hh, hd);
cudaMemcpy3DParms copyparms = {0};
copyparms.srcPtr = src;
copyparms.dstPtr = dest;
copyparms.extent = copyext;
copyparms.kind = cudaMemcpyHostToDevice;
cudaMemcpy3D(©parms);
【注:全部在浏览器中完成,切勿编译或运行使用风险自负】
有没有类似于 MATLAB 的三维矩阵索引的可能性?
这可以使用更高级别的库,例如libtorch 。 例如,
d_data(1:100, 1:200, 1:800) = h_data
与libtorch变得像
d_data.index_put_({Slice(0, 100), Slice(0, 200), Slice(0, 800)}, h_data)
(MATLAB 使用基于 1 的索引)。
可能还有其他 C++ 库可以做到这一点,但这是我所知道的。
另一方面,如果创建一个 0 填充的 3D 数组是您唯一的目标,那么添加对另一个库的依赖可能不值得。 这个狭窄的目标可以通过主机上的三重循环或设备上的等效内核来实现。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.