在本地内存中分配一个常量内存变量,仅一次,在其工作组内共享

Allocate a constant memory variable in local memory, only once, shared within its workgroup

我有一个 OpenCL 应用程序,其内核都共享两大块常量内存。其中一个用于生成密码,另一个用于测试它。

这两个子程序在单独运行时非常快,但是当我运行他们一个接一个地运行时,事情就慢到停止了(我有我通常能得到的四分之一的性能)。

我相信这是因为测试密码的子例程有一个巨大的 (10k) 查找 table 用于 AES 解密,并且这不会在多个内核之间共享 运行 同时在同一工作组内。

我知道它不是共享的,因为 AES 查找 table 在每个内核中分配为 __local,然后初始化从外部库复制值(如内核创建静态内存的本地副本并使用它)。

我试过将 __local allocation/initialization 更改为 __constant 变量,一个指向库常量内存的指针,但这让我得到了 10x性能降低.

我无法理解这一点。我应该怎么做才能确保我的常量内存只为每个工作组分配一次,并且在同一工作组中工作的每个内核都可以在那里共享读取操作?

__constant 根据定义,内存由所有工作组共享,因此我希望在任何合理的实现中它只在每个内核的计算设备上分配一次。

另一方面,如果你有两个独立的内核,你正在背靠背排队,我想不出一个合理的方法来保证一些 __constant 内存在两者的设备。如果你想合理地确定一些缓冲区被复制到计算设备一次供两个子程序使用,那么子程序应该是同一个内核的一部分。

一般来说,性能将取决于底层硬件和 OpenCL 实现,并且不会因 table 跨不同设备而异。您应该看看是否有适用于您正在使用的硬件的 OpenCL 性能指南。

至于为什么 __constant内存可能比__local内存慢,同样取决于硬件和OpenCL实现如何映射地址spaces 到硬件上的内存位置。您的错误是假设 __constant 内存会更快,因为它根据定义是一致的。 内存在设备上的位置将决定它的速度(即每个工作组的快速缓冲区与设备上所有工作组共享的较慢的缓冲区)和 OpenCL地址 space 只是 how/where OpenCL 实现分配内存的一个因素。 (大小也很重要,可以想象,如果您的 __constant 内存足够小,那么每个工作组的内存将 "promoted" 更快,但这完全取决于实现。)

如果 __local 内存如您所说更快,那么您可以考虑将您的工作拆分为工作组大小的块,并仅传入工作所需的 table 部分作为内核参数分组到 __local 缓冲区。