1

我正在研究如何将每行的可变宽度的二维数组复制到 GPU 中。

int rows = 1000;
int cols;
int** host_matrix = malloc(sizeof(*int)*rows);
int *d_array;
int *length;

...

每个都host_matrix[i]可能有不同的长度,我知道length[i],这就是问题开始的地方。我想避免复制虚拟数据。有更好的方法吗?

根据这个线程,这不是一个聪明的方法:

cudaMalloc(d_array, rows*sizeof(int*));  
for(int i = 0 ; i < rows ; i++)    {  
    cudaMalloc((void **)&d_array[i], length[i] * sizeof(int)); 
}  

但我想不出任何其他方法。还有其他更聪明的方法吗?可以使用 cudaMallocPitch 和 cudaMemCpy2D 改进它吗?

4

2 回答 2

5

在 CUDA 中为 GPU 分配指针数组的正确方法是这样的:

int **hd_array, **d_array;
hd_array = (int **)malloc(nrows*sizeof(int*));
cudaMalloc(d_array, nrows*sizeof(int*));  
for(int i = 0 ; i < nrows ; i++)    {  
    cudaMalloc((void **)&hd_array[i], length[i] * sizeof(int)); 
}
cudaMemcpy(d_array, hd_array, nrows*sizeof(int*), cudaMemcpyHostToDevice);

(免责声明:用浏览器编写,从未编译,从未测试,使用风险自负)

这个想法是您首先在主机内存中组装设备指针数组的副本,然后将其复制到设备。对于有 1000 行的假设情况,这意味着 1001 次调用cudaMalloc,然后 1001 次调用cudaMemcpy只是为了设置设备内存分配并将数据复制到设备中。这是一个巨大的间接费用惩罚,我建议不要尝试它;表现将非常糟糕。

如果您有非常参差不齐的数据并且需要将其存储在设备上,我是否建议您借鉴所有参差不齐的数据问题的根源 - 大型非结构化稀疏矩阵 - 并为您的数据复制其中一种稀疏矩阵格式。使用经典的压缩稀疏行格式作为模型,您可以执行以下操作:

int * data, * rows, * lengths;

cudaMalloc(rows, nrows*sizeof(int));
cudaMalloc(lengths, nrows*sizeof(int));
cudaMalloc(data, N*sizeof(int));

在此方案中,将所有数据存储在单个线性内存分配data中。锯齿状数组的第 i 行从 开始,data[rows[i]]每行的长度为length[i]。这意味着您只需要三个内存分配和复制操作即可将任意数量的数据传输到设备,而不是nrows在您当前的方案中,即。它将开销从 O(N) 减少到 O(1)。

于 2012-09-18T20:33:11.213 回答
0

我会将所有数据放入一个数组中。然后用行长度组成另一个数组,使得 A[0] 是第 0 行的长度,依此类推。所以 A[i] = length[i] 那么你只需要在卡上分配 2 个数组并调用 memcopy 两次。
当然这是一些额外的工作,但我认为性能方面会有所改进(当然取决于你如何使用卡上的数据)

于 2013-08-09T23:19:20.080 回答