将2D阵列复制到已知可变宽度的GPU

时间:2012-09-18 15:29:17

标签: cuda gpu gpgpu nvidia

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

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

...

每个host_matrix[i]可能有不同的长度,我知道length[i],并且问题就出现了。我想避免复制虚拟数据。有没有更好的方法呢?

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

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

但我想不出任何其他方法。有没有其他更聪明的方法呢? 可以使用cudaMallocPitch和cudaMemCpy2D ??

进行改进

2 个答案:

答案 0 :(得分: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只是为了设置设备内存分配并将数据复制到设备中。这是一个巨大的开销罚款,我会反对尝试它;表现真的很糟糕。

如果您有非常锯齿状数据并需要将其存储在设备上,我是否可以建议对所有锯齿状数据问题的母亲提示 - 大型非结构化稀疏矩阵 - 并复制其中一个相反,您的数据的稀疏矩阵格式。使用经典compressed sparse row格式作为模型,您可以执行以下操作:

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)的开销。

答案 1 :(得分:0)

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