我有一个存储在GPU中的2D数组dev_histogram和存储在CPU中的2D数组histogarm。我想将dev_histogram的内容复制到直方图中。以下是我的程序的相关部分。我也可以发布完整的代码。
int *dev_histogram; // Array for histogram, GPU
int histogram[SIZE_THETA][SIZE_RHO]; // Array for histogram, CPU
size_t pitch;
histogramSize = sizeof(int) * SIZE_THETA * SIZE_RHO;
cudaMallocPitch((void**)&dev_histogram, &pitch, SIZE_THETA * sizeof(int), SIZE_RHO)
houghTransformation << <width, height >> >(dev_edges, dev_histogram, pitch, n_pixels, width, height);
// Here I get a Segmentation fault:
cudaMemcpy2D(histogram, pitch, dev_histogram, SIZE_THETA * sizeof(int), SIZE_THETA * sizeof(int), SIZE_RHO * sizeof(int), cudaMemcpyDeviceToHost)
你能帮我理解如何复制我的矩阵吗?大多数情况下,我对作为我的来源的投放感到困惑。
答案 0 :(得分:1)
在CUDA工具包参考手册中,您可以看到cudaMallocPitch中的音高是您正在复制的2D阵列的分配宽度(以字节为单位)。你的dev_histogram的实际宽度等于音高和高度等于你指定的高度。 2D数组的每一行都分配了间距字节,但只有宽度* sizeof(int)字节的有效数据。
在同一份文件中,cudaMemcpy2D的原型是
cudaError_t cudaMemcpy2D (void ∗ dst, size_t dpitch, const void ∗ src, size_t spitch, size_t width, size_t height, enum cudaMemcpyKind kind)
这里dst是主机上的数组,dpitch是目标数组(histogram)的字节宽度,spitch是源数组的宽度(dev_histogram)。宽度和高度是2D数组的尺寸。 你必须这样调用它:
cudaMemcpy2D(histogram, SIZE_THETA*sizeof(int), dev_histogram, pitch, SIZE_THETA * sizeof(int), SIZE_RHO, cudaMemcpyDeviceToHost);
编辑:在ArchaeaSoftware之后,我注意到确实高度确实是行数,高度的字节数没有意义。更新了答案,因为您仍然需要更改音高。
答案 1 :(得分:1)
指定SIZE_RHO作为高度,而不是SIZE_RHO * sizeof(int):
<cudaMemcpy2D(histogram, pitch, dev_histogram, SIZE_THETA * sizeof(int), SIZE_THETA * sizeof(int), SIZE_RHO * sizeof(int), cudaMemcpyDeviceToHost);
>cudaMemcpy2D(histogram, pitch, dev_histogram, SIZE_THETA * sizeof(int), SIZE_THETA * sizeof(int), SIZE_RHO, cudaMemcpyDeviceToHost);
答案 2 :(得分:0)
通常,当将数据存储在连续内存中时,您希望使一段内存的维度为存储单元的倍数,以便可以有效地读取数据。例如,您可以读取一个32位字,而不是读取一行中的4个单独字节。你这样做是为了提高效率。查找内存对齐。
出于同样的原因,你想让某些数组具有pitch * height的大小,其中pitch是宽度四舍五入到你正在使用的任何存储单元的最接近的倍数。如果你的数组是31 * 5那么你使用的是32的间距但是31的宽度。预计4个32位读取比31个1字节读取快。您丢弃额外的“填充”字节。
你可能想设置pitch = width。你的seg错误的原因是你没有初始化它。检查宽度和高度是否与线程块大小的GPU规格兼容。