【发布时间】:2012-04-10 18:26:36
【问题描述】:
我正在研究一个内核,它每个线程都有很多全局内存访问,所以我将它们复制到本地内存,这样可以提高 40% 的速度。
我想要更快的速度,所以从本地复制到私有会降低性能
那么我认为我们不能使用太多可能会降低性能的私有内存是否正确?
【问题讨论】:
-
一个最小的可运行示例和确切的平台规格会很棒:-)
标签: opencl
我正在研究一个内核,它每个线程都有很多全局内存访问,所以我将它们复制到本地内存,这样可以提高 40% 的速度。
我想要更快的速度,所以从本地复制到私有会降低性能
那么我认为我们不能使用太多可能会降低性能的私有内存是否正确?
【问题讨论】:
标签: opencl
Ashwin 的回答方向正确,但有点误导。
OpenCL 将变量的地址空间从物理存储中抽象出来,两者之间不一定存在 1:1 的映射关系。
考虑在 __private 地址空间中声明的 OpenCL 变量,默认情况下,函数内部包含自动非指针变量。 NVidia GPU 实现会尽可能将这些物理分配到寄存器中,只有在寄存器容量不足时才会溢出到物理片外内存。这种特殊的片外内存称为“CUDA 本地”内存,具有与为 __global 变量分配的内存相似的性能特征,这解释了由于寄存器溢出导致的性能损失。在这个实现中没有“私有内存”这样的物理东西,只有一个“私有地址空间”,可以在片内或片外分配。
性能损失并不是使用私有地址空间(或“私有内存”)的直接后果,私有地址空间通常分配在高性能内存中。这是因为,在这种实现下,变量太大而无法分配到高性能寄存器上,因此被“溢出”到了片外内存。
【讨论】:
(我知道这是一个老问题,但给出的答案不是很准确,而且我在 Google 搜索期间在其他地方看到了相互矛盾的答案。)
根据“Heterogeneous Computing with OpenCL”(OpenCL 1.2 修订版):
私人记忆是单个工作项独有的记忆。局部变量 和非指针内核参数默认是私有的。在实践中,这些变量 通常映射到寄存器,尽管私有数组和任何溢出的 寄存器通常映射到片外(即长延迟)内存。
所以,如果你使用大量私有内存,或者在私有内存中使用数组,是的,它可能会比本地内存慢。
【讨论】:
在(类似 GPU 的)OpenCL 设备中,本地内存位于芯片上并靠近处理元件 (PE)。它可能与访问 L1 缓存一样快。每个线程的私有内存实际上是从片外全局内存中分配的。这离PE很远,可能会有数百个时钟周期的延迟,从而降低读写性能。
【讨论】:
James Beilby 的回答是正确的方向,但有点偏题:
根据实现,它可能更快或更慢,因为 opencl 不会强制提供商使用片上或片外存储器,但 AMD 在价格/性能方面非常擅长 OpenCL,所以我将给出一些关于它。
AMD 实现中的私有内存速度最快(延迟最短,带宽最高,例如主流 GPU 的 22 TB/s)。
在附录-d中:
你可以看到 register 文件、LDS、constant cache 和 global 它们用于不同的命名空间当自己有足够的空间时。例如,寄存器文件有 22 TB/s,每个计算单元只有大约 300kB。这比用于 __local 内存空间的 LDS 具有更少的延迟和更多的带宽。总 LDS 大小甚至小于(每个计算单元)。
如果从本地到私有没有好处,您应该将本地线程组大小从 256 减少到 64,例如。所以每个线程可以使用更多的私有寄存器。
所以对于这个示例 AMD gpu,本地内存比全局内存快 15 倍,私有内存比本地内存快 5 倍。如果它不适合私有内存,它会溢出到全局内存,因此只有 L1-L2 缓存可以在这里提供帮助。如果数据没有被大量重复使用,那么在这里使用私有寄存器没有意义。如果只使用一次,只需从全局流式传输到全局即可。
对于某些智能手机或 cpu,使用私有寄存器可能非常糟糕,因为它们可以映射到其他东西。
【讨论】: