【问题标题】:send custom datatype/class to GPU将自定义数据类型/类发送到 GPU
【发布时间】:2014-05-01 21:26:27
【问题描述】:

GPGPU/Cuda 的所有教程和介绍材料都经常使用平面数组,但是我正在尝试移植一段代码,它使用比数组更复杂的对象。

我有一个 3 维 std::vector 我想在 GPU 上拥有它的数据。有哪些策略可以在 GPU 上实现这一点?

我暂时能想到 1:

  1. 将主机上的向量数据复制到更简单的结构中,例如数组。然而这似乎很浪费,因为 1) 我必须复制数据并然后发送到 GPU;和 2)我必须分配一个 3 维数组,其维度是任何向量中元素计数的最大值,例如使用二维向量

想象一下 {{1, 2, 3, 4, .. 1000}, {1}},在主机内存中,这些大约是 ~1001 个分配的项目,而如果我要将其复制到二维数组,我将不得不分配 1000*1000 个元素。

有更好的策略吗?

【问题讨论】:

  • 您不必分配最大维度的 3D 数组。您只需要一个长度等于 3D std::vector 中 元素 数量的一维(即平面)数组。并且您需要每个子向量的起点的伴随(可能是一维)数组。 GPU 上的净存储要求可能最终类似于主机上 3D std::vector 的存储要求。有很多方法可以重构数据以适应 GPU。这个问题很宽泛。
  • 谢谢罗伯特,对于第一部分,您的评论很可能是一个(接受的)答案。但是您因此确认需要重构主机上的数据结构?我希望有一些(cuda)函数可以获取对象(类或结构),并且可以有效地将实际值深度复制到设备,而无需先复制到主机内存中。
  • 我可以建议最接近自动深度复制的是统一内存。但这仍然涉及一些代码重构,有一些特定的要求,目前不一定是一种高性能的方法。我发布了一个答案,其中包含一些要调查的事情的建议。尽管std::vector 的重构可能无关紧要,但许多类型的数据结构应该被重构以在 GPU 上产生更高的性能。

标签: cuda gpgpu


【解决方案1】:

有许多方法可以重构数据以适应 GPU 计算,其中一个挑战是在设备和主机之间复制数据,另一个挑战是在 GPU 上表示数据(以及算法设计)以有效利用内存带宽.我将重点介绍 3 种通用方法,重点是在主机和设备之间轻松复制数据。

  1. 既然您提到了std::vector,您可能会看看thrust,它具有与GPU 计算兼容的向量容器表示。然而,推力不能方便地处理向量 AFAIK 的向量,我将其解释为您的“3D std::vector”命名法。所以仍然会涉及一些(非平凡的)重构。并且推力仍然不允许您在普通 CUDA 设备代码中直接使用向量,尽管它们包含的数据是可用的。

  2. 您可以手动将向量向量重构为平面 (1D) 数组。您需要一个数组来存储数据元素(长度 = 包含在“3D”std::vector 中的元素总数),再加上一个或多个附加 (1D) 向量来存储起点(以及隐含终点)点每个单独的子向量。是的,人们会说这是低效的,因为它涉及间接或指针追逐,但是so does the use of vector containers on the host。我建议让你的算法首先工作比担心数据访问的某些方面的一级间接性更重要。

  3. 正如您所指出的,CUDA 的“深拷贝”问题可能是一个乏味的问题。它很新,但您可能想看看Unified Memory,它在 CUDA 6 下的 64 位 Windows 和 linux 平台上可用,带有 Kepler (cc 3.0) 或更新的 GPU。尤其是对于 C++,UM 可以非常强大,因为 we can extend operators 就像 new 在底层一样,并且为共享主机/设备分配提供了几乎无缝的 UM 使用。

【讨论】:

  • 在我的情况下 2. 是唯一可行的选择,它是一个大型应用程序,其中只会卸载非常昂贵的操作,因此我无法将其转换为推力,并希望它适用于其他所有人. 3. 也引起了我的注意,但我只有 Fermi 硬件的可用性。所以,我得做一个 flatten 方法
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多