【问题标题】:OpenCL enqueued kernels using lots of host memoryOpenCL 使用大量主机内存将内核排入队列
【发布时间】:2015-08-11 16:29:59
【问题描述】:

我正在使用 OpenCL 内核对我的系统的大量副本执行蒙特卡罗扫描。在最初的调试阶段之后,我将一些参数增加到更实际的值,并注意到程序突然消耗了大量的主机内存。我正在对大约 4000 个副本执行 1000 次扫描,每次扫描由 2 个内核调用组成。这会导致大约 800 万次内核调用。

内存使用的来源很容易找到(见截图)。

  • 在将内核执行排入队列时,内存使用量会上升。
  • 在内核执行期间,内存使用量保持不变。
  • 内核完成后,使用情况将恢复到原始状态。
  • 我没有分配任何内存,如内存快照所示。

这意味着 OpenCL 驱动程序正在使用内存。我知道它必须保留内核调用的所有参数以及全局和本地工作组大小的副本,但这并没有加起来。

内存使用峰值为 4.5GB。在对内核进行排队之前,大约使用了 250MB。这意味着 OpenCL 为 800 万次调用使用了大约 4.25GB,即每次调用大约 0.5 KB。

所以我的问题是:

  • 这种内存使用情况正常吗?
  • 是否有好的/已知的技术来减少内存使用?
  • 也许我不应该同时将这么多内核排入队列,但是如何在不导致同步的情况下做到这一点,例如clFinish()?

【问题讨论】:

  • 每 100 或 1000 次内核调用尝试clFlush,如果您发现它会损害性能,则更少尝试。这是一个非阻塞命令,它将向设备发出所有先前排队的命令。
  • 感谢您的提示!我在每 1000 次内核调用后添加了一个clFlush,这已经对其进行了一些改进。峰值内存使用量下降到 3.5GB,并且峰值要短得多,即下降的斜率开始得更早,但没有那么陡峭。对性能的影响要么很小,要么不存在,我看不到任何影响。
  • 好的,试试clWaitForEvents。将 1000 个内核排入队列,在最后一个上添加一个事件,然后将另外 999 个内核排入队列并调用clWaitForEvents。这将使它等待第 1000 个内核完成,而队列中已经有另外 999 个内核。然后类似地重复整个过程。
  • 太棒了,它降到了 750MB。 clFlushclWaitForEvents 之前有任何意义吗?我没有发现任何区别。
  • clFlush 就在clWaitForEvents 之前,而不是因为我认为它是由clWaitForEvents 完成的。如果您想让内存减少超过 750MB,我会尝试减少等待内核完成之后的数字,例如减少到 500。需要计算出这个数字,以便最适合您的场景。我将把我们在这里所做的作为答案,如果您满意,请接受。

标签: opencl


【解决方案1】:

需要以某种可控的方式将大量内核调用加入队列,以便命令队列不会占用太多内存。首先,clFlush 可能在一定程度上有所帮助,然后clWaitForEvents 需要在中间创建一个同步点,例如 2000 个内核调用被排队,clWaitForEvents 等待第 1000 个。设备不会暂停,因为我们已经预先批处理了另外 1000 次工作调用。然后类似的事情需要一次又一次地重复。可以这样说明:

enqueue 999 kernel commands
while(invocations < 8000000)
{
    enqueue 1 kernel command with an event
    enqueue 999 kernel commands
    wait for the event
}

我们应该等待的最佳内核调用次数可能与此处介绍的不同,因此需要针对给定场景进行计算。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-11
    • 1970-01-01
    • 1970-01-01
    • 2020-01-17
    • 1970-01-01
    相关资源
    最近更新 更多