我有一个运行良好的应用程序有一个奇怪的问题,但有一些不合理的性能损失。该应用程序和代码是私有的,但我可以在这里给出它的一些详细工作模式(简化了很多)。
我的应用程序使用 4 个内核:
1. Preprocesses
Reads "I" buffer; Writes to "T" buffer
2. Process
Reads + Writes "T" buffer
3. Parse & Preprocess
Reads + Writes "T" buffer, & writes "O" buffer
4. Check
Reads "O" buffer; Writes to "C" buffer (result of Check)
所有缓冲区都保存到设备中。“I”和“O”缓冲区各为 200kB 缓冲区。“T”缓冲区大约 20MB,从未在 GPU 之外使用。“C”缓冲区只是给出结果的 4 字节 int。
该系统以 3 种不同的形式运行:
- Pure iterative: Write,1,2,3,2,3,2,3,.....,2,3,Read
- Iterative + Reading intermediate: Write,1,2,3,Read,2,3,Read,2,3,.....,2,3,Read
- Iterative + Check: Write,1,2,3,4,Read(C),2,3,4,Read(C),2,3,.....,2,3,Read
在第一种模式下,所有内核都立即排队,我对该模式没有任何问题,只是以最大 GPU 利用率(和 CPU)运行。其他 2 种模式使用内核的渐进式排队,如果读取的值不正确,则将一组新的内核排队。
然而,在第二种和第三种模式中,每次从设备读取后,设备都会保持空闲一段时间。我已经对程序进行了概要分析,每次读取后都存在没有 GPU 使用时间的小间隙(100us)。在写入部分之后不会发生这种情况。我为 I/O 和执行创建了 2 个单独的队列以启用并行化,但没有运气。
差距是这样的(我明天可以发布视觉分析器的屏幕):
- 写,1,2,3,读,2, GAP ,3,Read,2, GAP ,3,.....,2,3,读
据我测试,此问题出现在 HD5770、HD5570、GTX570、C2050、C2070 上。在windows和linux中。但是在 Quadro 2000M 中运行得非常好,甚至可以进行并行内核执行和 I/O!
有什么我想念的吗?固定内存是否比手动 clCreate + clWrite/Read 更快?它能解决这个问题吗?我意识到我可以在该间隙中多次运行内核 2,但无法运行内核 3,内存“O”是否以某种方式受到保护并阻止内核 3 运行?
PD:我在模式中有一些 clWaitForEvents 有差距。我测试了删除它们,差距缩小了大约 50%,但 CPU 使用率从 20% 增加到 100%。这可能与 CPU 或调度程序/驱动程序有关吗?