【问题标题】:Writing to local memory in OpenCL slows kernel by 400%?在 OpenCL 中写入本地内存会使内核速度减慢 400%?
【发布时间】:2015-08-05 05:39:43
【问题描述】:

我有一个非常复杂的内核,我一直在优化。无需遍历所有代码,有一个内核可以将一些值写入全局内存。

然后第二个内核触发并对该数据进行数十亿次计算,所有这些都在本地内存中。我一遍又一遍地优化代码,将内核运行时间降低到大约 275 毫秒。

内核的最后一部分在本地内存中处理的数据数组上循环并搜索匹配的字符串。显然,如果它找到匹配项,则需要让主机程序知道这一点。我通过将 global_array[0].x 更改为 999 并将 global_array[0].y 更改为等于找到的结果来完成此操作。

内核完成后,它会读取 global_array 的第一个元素,检查是否 .x == 999,如果是,我们知道我们找到了目标。

在做更多优化的过程中,我发现如果我注释掉 global_array[0] = 行,内核运行速度是原来的 4 倍,大约为 62 毫秒。知道全局内存很慢,我开始测试各种东西。我想,嘿,也许如果我更改 LOCAL 数组,那么最后将 work_group_copy 复制回 global 我会得到一点速度提升。

但是不……我不知道。这真是令人困惑。如果在内核结束时,我将任何内容写入全局或本地内存中的任何位置,我的内核运行时间为 270 毫秒。如果我将相同的数据写入私有变量,或者只是执行其他不相关的代码,则为 62 毫秒。

我需要以某种方式从内核返回结果 - 但由于某种原因,写入局部变量,内核在到达终点之前执行 50 倍而不减速,似乎在写入时像疯了一样放慢速度结束。

谁能解释为什么会发生这种情况?我被难住了。

【问题讨论】:

标签: memory-management opencl


【解决方案1】:

当您不写出全局内存时,JIT 编译器很可能会将您的大部分代码检测为死代码,并将其消除。

【讨论】:

  • 啊...所以仅仅通过计算,而不是真正返回一些东西或“显示”我已经完成了我所做的工作,编译器基本上跳过了实际做的工作?所以当我输入任何类型的返回值时,它会看到它的工作正在被使用,所以它真的做到了吗?说得通。如果对结果什么都不做,就没有理由做这项工作。任何人都可以确认是这种情况吗? (在走开之前,我想知道它 IS 而不是“最有可能是”)
  • 您可以自己确认。保留对全局内存的写入,但用常数替换复杂的计算。如果您想看看是否有区别,请尝试本地和全局内存。
【解决方案2】:

要验证我们需要查看代码。您可以验证的一种方法是保留写出部分,但要使用您知道永远不会满足的条件来保护它(但编译器不可能知道 - 例如,包含特定值的某个全局地址) .您也必须小心这一点,因为编译器可以执行代码运动以在线程中更早地检查条件以仍然跳过工作。因此,条件(永远不会满足)需要基于您所做的一些实际工作的结果(或者有可能受到它的影响,或者足够复杂以至于编译器认为可能存在依赖关系) .顺便说一句,我曾经编写过用于测量 gpg 性能的 OCL 微基准测试,而这些东西是你在早期学到的东西之一 - 试图欺骗编译器而不是优化你正在尝试测量的工作是一场持续不断的战斗。

【讨论】:

    猜你喜欢
    • 2012-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-08
    • 2017-11-17
    • 2023-03-30
    • 2016-06-16
    • 2011-09-07
    相关资源
    最近更新 更多