我很擅长在AMD GPU(夏威夷核心或Radeon R9 390)上使用OpenCL获得一些性能。
操作如下:
依赖是:
内存传输和内核执行在两个单独的命令队列中执行。命令依赖性由OpenCL中定义的GPU事件完成。
现在整个操作仅用于使用相同输入数据进行性能分析。
正如您在时间轴中看到的那样,主机在GPU上等待很长时间以完成clWaitForEvents(),而GPU大多数时间都处于闲置状态。您还可以看到重复操作。为方便起见,我还提供了所有已发布的OpenCL命令的列表。
我现在的问题是:
为什么GPU如此闲置?在我的脑海中,我可以轻松地将所有“蓝色”物品组合在一起并立即开始操作。内存传输速率为6 GB / s,这是预期的速率。
为什么内核执行得这么晚?为什么内核#2和内核#3执行之间存在差距?
为什么内存传输和内核不能并行执行?我使用2个命令队列,只有1个队列,性能更差。
只需将所有命令推到我的脑海中(当然保持依赖性,所以第一个绿色必须在第一个蓝色之后开始)我可以将性能提高三倍。我不知道为什么GPU如此迟钝。有谁有点洞察力?
一些数字运算
内存传输#3为143μs - 由于未知原因总是过高,应该是#2的1/2或70-80μs
内核#1是74μs
因为内核#1比内存转移#2快,而内核#2比内存转移#3快整体时间应该是:
但是clWaitForEvents是
是的,有一些损失,我很好,如10%(60μs),但300%太多了。
答案 0 :(得分:2)
正如@DarkZeros所说,你需要通过使用多个命令队列在时间线上重叠它们来隐藏内核入队开销。
为什么GPU如此闲置?
因为您正在使用2个命令队列,并且它们正在串行运行(可能),因为事件会使它们等待更长时间。
如果所有内容都是串行的,您应该使用单个队列。如果您可以添加双缓冲或类似技术来推进计算,则应该让两个队列重叠操作。
为什么内核执行得这么晚?
宽孔包括主机端延迟,例如排队命令,刷新命令到设备,主机端算法和设备端事件控制逻辑。也许事件可以小到20-30微秒,但主机设备的相互作用不止于此。
如果你摆脱了事件并使用单个队列,驱动程序甚至可以添加早期的计算技术来填补这些空白,甚至在你排队这些命令之前(可能)就像CPU进行早期分支(预测)一样。
为什么内存传输和内核不能并行执行?
没有强制执行,但驱动程序也可以检查内核和副本之间的依赖关系并保持数据完整,它们可以暂停某些操作,直到其他操作完成(可能)。
您确定内核和缓冲区副本完全独立吗?
另一个原因可能是两个队列没有多少选择重叠。如果两个队列都有两种类型的操作,那么它们将有更多的重叠选项,例如内核+内核,复制+复制而不仅仅是内核+复制。
如果程序有太多小内核,你可以尝试OpenCL 2.0动态并行,这使得设备调用内核本身比主机端入队更快。
也许你可以添加更高级别的并行性,例如图像级并行性(如果你的图像处理),以保持gpu忙。同时处理5-10个图像,这应该确保独立的内核/缓冲区执行,除非所有图像都在同一个缓冲区中。如果这不起作用,那么您可以启动相同程序的5-10个进程(进程级并行)。但是有太多的上下文可能会导致驱动程序的限制,因此图像级并行性必须更好。
R9 390必须能够处理8-16个命令队列。
1758μs
有时即使空核也会等待500-100μs。最有可能你应该排队1000个周期,最后等一次。如果在用户按钮单击后每个循环都有效,那么用户就不会注意到1.7毫秒的延迟。