我有一个OpenCL应用程序,其内核共享两大块常量内存。其中一个用于生成密码,另一个用于测试密码。
这两个子程序在单独操作时速度非常快,但是当我一个接一个地运行它们时,事情就会慢慢停止(我通常会得到四分之一的性能)。
我认为这是因为测试密码的子程序有一个巨大的(10k)AES解密查找表,并且在同一工作组内同时运行的多个内核之间不共享。
我知道它没有被共享,因为AES查找表在每个内核中被分配为__local
,然后初始化从外部库复制值(如同,内核创建静态的本地副本)记忆并使用那个)。
我尝试将__local
分配/初始化更改为__constant
变量,这是一个指向库常量内存的指针,但这会让我的性能降低<10倍
我无法理解这一点。我应该怎样做才能确保每个工作组只分配一次常量内存,同一工作组中的每个内核都可以在那里共享读操作?
答案 0 :(得分:2)
__constant
内存由所有工作组共享,因此我希望在任何合理的实现中,它只在每个内核上分配一次在计算设备上。
另一方面,如果你有两个独立的内核,你背靠背排队,我想不出一个合理的方法来保证在设备上共享或保留一些__constant
内存都。如果你想合理地确定某个缓冲区被复制一次到计算设备以供两个子程序使用,那么子程序应该是同一个内核的一部分。
一般来说,性能取决于底层硬件和硬件。 OpenCL实现,它不能在不同的设备上移植。您应该看看是否有正在使用的硬件的OpenCL性能指南。
至于为什么 __constant
内存可能比__local
内存慢,这又取决于硬件以及OpenCL实现如何将地址空间映射到硬件上的内存位置。你的错误在于假设__constant
内存会更快,因为它的定义是一致的。 其中设备上的内存将决定它的速度(即快速的每工作组缓冲区,与设备上所有工作组共享的较慢缓冲区)和OpenCL地址空间是只有一个因素是OpenCL实现将如何/在何处分配内存。 (大小也很重要,可以想象,如果你的__constant
内存足够小,它将被“提升”到更快的每工作组内存,但这完全取决于实现。)
如果你说__local
内存更快,那么你可以考虑将你的工作分成工作组大小的块,并只将工作组所需的那部分表传入{{1缓冲区作为内核参数。