我对在 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 事件完成。
整个操作现在循环,只是为了使用相同的输入数据进行性能分析。
正如您在时间线中看到的,主机在 GPU 上等待很长时间才能完成 clWaitForEvents(),而 GPU 大部分时间都处于空闲状态。您还可以看到重复的操作。为方便起见,我还提供了所有已发布 OpenCL 命令的列表。
我现在的问题是:
为什么GPU闲置这么多?在我的脑海中,我可以轻松地将所有“蓝色”项目组合在一起并立即开始操作。内存传输为 6 GB/s,这是预期的速率。
为什么内核执行得这么晚?为什么内核 #2 和内核 #3 执行之间存在差距?
为什么内存传输和内核不并行执行?我使用 2 个命令队列,只有 1 个队列,性能更差。
只需将所有命令放在我的脑海中(当然要保持依赖关系,所以第一个绿色必须在第一个蓝色之后开始),我可以将性能提高三倍。我不知道为什么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% 太多了。