【问题标题】:How to reduce OpenCL enqueue time/any other ideas?如何减少 OpenCL 排队时间/任何其他想法?
【发布时间】:2019-01-18 01:22:18
【问题描述】:

我有一个算法,我一直在尝试在我的 nVidia 上使用 OpenCL 来加速它。

它必须处理大量数据(比如说 100k 到百万),其中对于每个数据:必须首先更新一个矩阵(在设备上)(使用数据和两个向量);只有在整个矩阵更新后,两个向量(也在设备上)使用相同的数据更新。所以,我的主机代码看起来像这样

for (int i = 0; i < milions; i++) {
        clSetKernelArg(kernel_matrixUpdate, 7, sizeof(int), (void *)&i); 
        clSetKernelArg(kernel_vectorsUpdate, 4, sizeof(int), (void *)&i);       
        clEnqueueNDRangeKernel(command_queue, kernel_matrixUpdate, 1, NULL, &global_item_size_Matrix, NULL, 0, NULL, NULL);
        clEnqueueNDRangeKernel(command_queue, kernel_vectorsUpdate, 1, NULL, &global_item_size_Vectors, NULL, 0, NULL, NULL);}

不幸的是,这个循环的执行时间比内核本身要长。所以我的问题是:

  • 有什么方法可以更有效地将 N 个内核排入队列?
  • 有没有办法先更新整个矩阵,然后更新向量,而不使用单独的内核?例如。设备是否按顺序运行内核(即第一个工作组为 0,1,...,63;第二个工作组为 64,...)?但我想这无论如何都是一个不好的做法......
  • 还有其他想法吗? :D

我们将不胜感激每一个反馈或意见。谢谢。

【问题讨论】:

  • 最快的是使用 OpenCL 2.0 动态并行的设备端排队。此外,如果内核参数始终相同,则无需使用 clSetKernelArg 重新设置它们。一次就够了。如果您在创建时未指定无序标志,则内核默认按顺序运行。还有为什么(void *)&amp;i?它正在获取变量的地址,因此所有内核参数都将获得相同的最新值。他们都会看到millions-1 的价值。如果仅更改该参数,则可以添加第二个内核以在 gpu 内存中增加该值,然后将它们逐个设备排入队列。至少这会跳过 CPU 端。
  • 那么您只会将父内核排入队列一次。如果每个操作独立于另一个,您可以使用多个命令队列(可能多达 64 个)同时运行多个内核。
  • 不幸的是,nVidia 目前似乎不支持 OpenCL 2.0 :(
  • 听起来你的问题不在于 OpenCL,而是你的算法是顺序的。您确定不能更改算法以便批量更新吗?至少,如果您受 API 限制,一个明显的步骤是将您的 2 个内核合并为 1 个。(您可以将矩阵大小与向量大小联系起来吗?)但除此之外您不会得到太多帮助,除非您实际上发布您的算法的性质,因为这是需要优化的。

标签: parallel-processing opencl gpu gpgpu hardware-acceleration


【解决方案1】:

您需要将所有数据上传到 GPU,然后使用每个元素一个工作项调用内核,而不是 for 循环。

通常,当从 CPU 到 GPU 时,最外层的“for”循环成为内核调用。

【讨论】:

    猜你喜欢
    • 2022-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-08
    • 1970-01-01
    • 2010-10-23
    • 1970-01-01
    • 2012-04-17
    相关资源
    最近更新 更多