我有一个OpenCL核,它计算系统中其他粒子施加在粒子上的总力,然后再计算另一个粒子的位置/速度。我想并行这些内核跨越多个GPU,基本上分配一定数量的粒子给每个GPU。但是,我必须多次运行这个内核,并且每个GPU的结果都在其他的GPU上使用。让我进一步解释一下:
假设GPU 0上有0粒子,GPU 1上有1粒子。粒子0上的力是变化的,粒子1上的力也是一样,然后积分器就相应地改变了它们的位置和速度。然后,这些新的位置需要放置在每个GPU上(两个GPU都需要知道粒子0和粒子1的位置),这些新的位置用于计算下一步每个粒子上的力,积分器使用这些新位置,积分器的结果用于计算力等。本质上,所有缓冲区都需要在力计算开始时包含相同的信息。
因此,问题是:--考虑到每个GPU都有不同的缓冲区--跨GPU同步缓冲区的最佳方法是什么?如果我想要保持并行性,根据我最后一个问题,它们就不能有一个共享缓冲区(但是,如果有一种方法可以创建共享缓冲区,并且仍然保留多个GPU,我完全赞成这样做)。我怀疑每一步复制结果都会导致更多的减速,而不值得在GPU之间并行化算法。
我确实找到了这条线,但答案并不十分明确,它只适用于所有GPU中的单个缓冲区。我想知道,具体来说,Nvidia GPU(更具体地说,特斯拉M2090)。
编辑:实际上,按照在Khronos论坛上的帖子的说法,OpenCL工作组的一位代表说,共享上下文上的单个缓冲区确实会分布在多个GPU上,每个缓冲区都确保内存中有最新的信息。但是,我没有看到Nvidia GPU上的这种行为;当我在后台运行程序时使用watch -n .5 nvidia-smi时,我看到一个GPU的内存使用量上升了一段时间,然后下降,而另一个GPU的内存使用量上升了。有谁能为我指出正确的方向吗?也许只是他们的实施?
发布于 2012-07-25 20:38:01
听起来你好像遇到了实现上的问题。
SIGGRAPH提供了一个很好的演示,展示了使用多个具有共享内存的GPU的几种不同方法。幻灯片是这里。
我设想,在当前的设置中,您有一个包含多个具有多个命令队列的设备的上下文。对于你所做的,这可能是正确的方法。
OpenCL 1.2规范附录A说:
OpenCL内存对象..。使用上下文创建,并且可以在使用相同上下文创建的多个命令队列之间共享。
此外:
应用程序需要在主机处理器上实现跨线程的适当同步,以确保对共享对象状态的更改.按正确的顺序发生..。当多个线程中的多个命令队列对共享对象的状态进行更改时。
所以在我看来,计算粒子位置和速度的内核需要依赖于计算粒子间力的内核。听起来你已经知道了。
就你的问题提出更多的问题:
考虑到每个GPU都有不同的缓冲区,什么是最好的方法来同步跨GPU的缓冲区?
..。我认为答案是“不要让缓冲区分开。”在两个设备之间使用相同的cl_mem对象,方法是该cl_mem对象来自相同的上下文。
至于数据的真实位置..。正如您所指出的,这是实现定义的(至少据我从规范中可以看出)。您可能不应该担心数据位于何处,只需从两个命令队列访问数据即可。
我意识到这可能会引起一些严重的性能问题。实现可能会发展并变得更好,因此如果您现在按照规范编写代码,那么将来它可能运行得更好。
为了获得更好的(或最小的不同)缓冲区共享行为,您可以尝试的另一件事是让粒子数据成为一张地图。
如果有任何帮助的话,那么我们的设置(一组具有双C2070s的节点)似乎可以很好地共享缓冲区。有时,数据只保存在一个设备上,而另一些时候,数据可能在两个地方都存在。
总之,我认为这里的答案是以规范提供的最佳方式来实现它,并希望在实现方面最好。
希望我能帮上忙
瑞安
https://stackoverflow.com/questions/11636491
复制相似问题