OpenCL内核

时间:2017-07-13 11:12:26

标签: performance opencl ati codexl

我很擅长在AMD GPU(夏威夷核心或Radeon R9 390)上使用OpenCL获得一些性能。

操作如下:

  • 将内存对象#1发送到GPU
  • 执行内核#1
  • 将内存对象#2发送到GPU
  • 执行内核#2
  • 将内存对象#3发送到GPU
  • 执行内核#3

依赖是:

  • 内存对象#1上的内核#1
  • 内存对象#2上的内核#2以及内核#1的输出内存
  • 内存对象#3上的内核#3以及内核#1&的内存输出内存。 #2

内存传输和内核执行在两个单独的命令队列中执行。命令依赖性由OpenCL中定义的GPU事件完成。

现在整个操作仅用于使用相同输入数据进行性能分析。

CodeXL Timeline

正如您在时间轴中看到的那样,主机在GPU上等待很长时间以完成clWaitForEvents(),而GPU大多数时间都处于闲置状态。您还可以看到重复操作。为方便起见,我还提供了所有已发布的OpenCL命令的列表。

CodeXL Commands

我现在的问题是:

  1. 为什么GPU如此闲置?在我的脑海中,我可以轻松地将所有“蓝色”物品组合在一起并立即开始操作。内存传输速率为6 GB / s,这是预期的速率。

  2. 为什么内核执行得这么晚?为什么内核#2和内核#3执行之间存在差距?

  3. 为什么内存传输和内核不能并行执行?我使用2个命令队列,只有1个队列,性能更差。

  4. 只需将所有命令推到我的脑海中(当然保持依赖性,所以第一个绿色必须在第一个蓝色之后开始)我可以将性能提高三倍。我不知道为什么GPU如此迟钝。有谁有点洞察力?

    一些数字运算

    • 内存传输#1为253μs
    • 内存传输#2为120μs
    • 内存传输#3为143μs - 由于未知原因总是过高,应该是#2的1/2或70-80μs

    • 内核#1是74μs

    • 内核#2是95μs
    • 内核#3是107μs

    因为内核#1比内存转移#2快,而内核#2比内存转移#3快整体时间应该是:

    • 253μs+120μs+143μs+107μs=623μs

    但是clWaitForEvents是

    • 1758μs - 或大约3倍

    是的,有一些损失,我很好,如10%(60μs),但300%太多了。

1 个答案:

答案 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毫秒的延迟。

  • 使用多个队列。
  • 摆脱队列之间的事件(如果有的话)。
  • 让每个队列都做各种工作。
  • 在主机端单个等待事件之前进行多次迭代。
  • 如果OpenCL 2.0存在,请尝试设备端入队,但这仅适用于内核执行,而不适用于来自/来自主机的副本。