【问题标题】:2D arrays with contiguous rows on the heap memory for cudaMemCpy2D()cudaMemCpy2D() 的堆内存上具有连续行的二维数组
【发布时间】:2015-11-03 16:59:50
【问题描述】:

CUDA documentation 建议将 cudaMemCpy2D() 用于 2D 数组(类似地 cudaMemCpy3D() 用于 3D 数组)而不是 cudaMemCpy() 以获得更好的性能,因为前者更合适地分配设备内存。另一方面,所有cudaMemCpy 函数,就像memcpy() 一样,需要连续分配内存。

如果我将我的(主机)数组创建为例如float myArray[h][w];,这一切都很好。但是,如果我使用类似的东西,它很可能不会工作:

float** myArray2 = new float*[h];
for( int i = 0 ; i < h ; i++ ){
   myArray2[i] = new float[w];
}

这不是一个大问题,除非尝试将 CUDA 实施到现有项目中,这是我面临的问题。现在,我创建了一个临时 1D 数组,将我的 2D 数组的内容复制到其中并使用cudaMemCpy() 并在内核启动后重复整个过程以获得结果,但这似乎不是一种优雅/有效的方式。

有没有更好的方法来处理这种情况?具体来说,有没有办法在堆上创建一个具有连续分配行的真正二维数组,以便我可以使用cudaMemCpy2D()

P.S:我在之前的类似帖子中找不到这个问题的答案:

【问题讨论】:

  • 我不清楚为什么你的第二个链接不是解决方案。
  • @AnonMail,我可能是错的,但在那个问题中定义了一个容器(类似于 std::vector)。在内部,它使用一维数组来实现连续分配。也类似于 std::vector 和 std::map 不能使用指针直接访问容器的元素,而应该使用迭代器。我怀疑是否可以使用 memcpy() 复制此类对象的内容。
  • @RobertCrovella,感谢您的评论。这(在 HostToDevice 复制之前手动展平 2D 数组)正是我现在在我的应用程序中所做的。我希望找到一种不同的方法,这样我就可以利用 cudaMemCpy2D() 更有效的内存分配。看来这是唯一的办法了。
  • 我假设您根本不想修改主机(分配)代码。但这是不正确的。实际上,您愿意修改主机代码,但您希望在主机上保留双下标访问。在这种情况下,@DaleWilson 的回答是一个很好的建议。

标签: c++ arrays cuda


【解决方案1】:

分配大数组,然后使用指针算法找到行的实际开始。

float* bigArray = new float[h * w]
float** myArray2 = new float*[h]
for( int i = 0 ; i < h ; i++ ){
   myArray2[i] = &bigArray[i * w];
}

您的 myArray2 指针数组为您提供 C/C++ 样式的二维数组行为,bigArray 为您提供 CUDA 所需的连续内存块。

【讨论】:

  • 谢谢,@Dale Wilson。澄清一下,这样我可以将 myArray2 传递给 cudaMemCpy2D(),对吧?
  • 请注意,我编辑了我的帖子以使第一行成为 new float[hw] 而不是 new float*[hw]。抱歉错字。现在关于您的问题:您可能应该使用 bigArray 将数组传递给 CUDA,但您也可以使用 myArray[0]。在任何情况下,您都需要一个指向连续浮点数组的指针,而不是指向数组指针的指针,这是传递 myArray2 会给您的。
  • 太棒了!这正是我所希望的。谢谢。
  • @RobertCrovella,我没有。请详细说明为什么我不应该使用 myArray[0]?
  • 您可以使用myArray2[0]。在我现在删除的评论中,我说你应该使用bigArray 而不是myArray2。但您也可以使用myArray2[0],因为通过检查与bigArray 相同。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-06
  • 2013-02-05
  • 2019-07-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多