OpenCL - 多GPU缓冲同步

时间:2012-07-24 17:51:00

标签: opencl nvidia

我有一个OpenCL内核,用于计算系统中其他粒子施加的粒子上的总力,然后是另一个整合粒子位置/速度的粒子。我想在多个GPU上并行化这些内核,基本上为每个GPU分配一些粒子。但是,我必须多次运行此内核,并且每个GPU都会使用每个GPU的结果。让我再解释一下:

假设你在GPU 0上有粒子0,在GPU 1上有粒子1.粒子0上的力被改变,粒子1上的力也是如此,然后它们的位置和速度由积分器相应地改变。然后,需要在每个GPU上放置这些新位置(两个GPU都需要知道粒子0和粒子1都在哪里),并且这些新位置用于计算下一步中每个粒子上的力,这是由积分器,其结果用于计算力等,等等。基本上,所有缓冲区在力计算到来时都需要包含相同的信息。

所以,问题是:如果每个GPU都有不同的缓冲区,那么在GPU之间同步缓冲区的最佳方法是什么?如果我想保持并行性as per my last question,他们不能拥有单个共享缓冲区(但是,如果有一种方法可以创建共享缓冲区并且仍然保留多个GPU,我就是为了这一点)。我怀疑在每一步复制结果会导致比在GPU中并行化算法更慢的速度。

我确实找到this thread,但答案不是很明确,只适用于所有GPU上的单个缓冲区。我想特别了解Nvidia GPU(更具体地说,特斯拉M2090)。

编辑:实际上,根据this thread on the Khronos forums,OpenCL工作组的代表说,共享上下文中的单个缓冲区确实会分散在多个GPU上,每个GPU都在制作确保它具有内存中的最新信息。但是,我没有在Nvidia GPU上看到这种行为;当我的程序在后台运行时使用watch -n .5 nvidia-smi时,我看到一个GPU的内存使用量上升了一段时间,然后在另一个GPU的内存使用率上升时下降。有没有人可以指出我正确的方向?也许只是他们的实施?

1 个答案:

答案 0 :(得分:4)

听起来你遇到了实施问题。

来自SIGGRAPH的精彩演示文稿展示了使用多个GPU和共享内存的几种不同方法。幻灯片是here

我想,在您当前的设置中,您有一个包含多个具有多个命令队列的设备的上下文。对于你正在做的事情,这可能是正确的方法。

OpenCL 1.2 specification的附录A说:

  

OpenCL内存对象,[...]是使用上下文创建的,可以在使用相同上下文创建的多个命令队列之间共享。

此外:

  

应用程序需要在主机处理器上的线程之间实现适当的同步,以确保当多个命令队列中的多个命令队列时,对共享对象状态的更改以正确的顺序发生[...]线程正在改变共享对象的状态。

因此在我看来,计算粒子位置和速度的内核需要依赖于计算粒子间力的内核。听起来你已经知道了。

根据你的问题提出更多建议:

  

如果每个GPU都有不同的缓冲区,那么在GPU之间同步缓冲区的最佳方法是什么?

......我认为答案是“不要将缓冲区分开”。通过让cl_mem对象来自相同的上下文,在两个设备之间使用相同的cl_mem对象。

至于数据实际存在的位置......正如您所指出的那样,这是实现定义的(至少从规范中可以看出)。您可能不应该担心数据的存在位置,只需从两个命令队列中访问数据。

我意识到这可能会产生一些严重的性能问题。实现可能会发展并变得更好,所以如果你现在根据规范编写代码,它将来可能会运行得更好。

为了获得更好(或最不同)的缓冲区共享行为,您可以尝试的另一件事是将粒子数据设为地图。

如果有任何帮助,我们的设置(一堆具有双C2070的节点)似乎可以非常佳地共享缓冲区。有时,数据仅保留在一个设备上,有时可能在两个地方都存在数据。

总而言之,我认为这里的答案是以规范提供的最佳方式进行,并希望在实施方面做到最好。

我希望我能提供帮助,

赖安