OpenCL本地内存大小和计算单元数量

7
每个GPU设备(AMD,Nvidia或其他)都被分为几个计算单元(多处理器),每个计算单元都有固定数量的内核(顶点着色器/流处理器)。因此,一个设备有(计算单元) x (顶点着色器/计算单元)个同时处理器,但每个多处理器只有一小部分固定数量的__local内存(通常为16KB或32KB)。因此,这些多处理器的确切数量很重要。
现在我的问题是:
  • (a) 我如何知道设备上的多处理器数量?这与CL_DEVICE_MAX_COMPUTE_UNITS相同吗?我能否从规格说明书(例如http://en.wikipedia.org/wiki/Comparison_of_AMD_graphics_processing_units)中推断出来?
  • (b) 在购买 GPU 之前,我如何知道每个 MP 上有多少可用的__local内存?当然我可以在运行它的计算机上请求CL_DEVICE_LOCAL_MEM_SIZE,但我不知道如何从甚至像http://www.amd.com/us/products/desktop/graphics/7000/7970/Pages/radeon-7970.aspx#3这样的详细规格单中推断出来?
  • (c) 目前具有最大CL_DEVICE_LOCAL_MEM_SIZE的卡是什么?价格并不是很重要,但64KB(或更大)将为我编写的应用程序带来明显的好处,因为我的算法完全可并行化,但在每个 MP 内具有随机访问模式(遍历图的边缘)。

尝试在AMD/NVIDIA SDK中提供的示例中运行设备查询。如果您想了解特定设备的设备查询,有许多人已经将其放在网上。 - captain
1个回答

9
  1. CL_DEVICE_MAX_COMPUTE_UNITS应该可以给你计算单元的数量,否则您可以从适当的手册中了解它(AMD OpenCL编程指南Nvidia OpenCL编程指南
  2. AMD链接的指南包含有关每个计算单元可用本地内存的信息(通常为32kB / CU)。 对于NVIDIA,快速的谷歌搜索显示出这份文档,其中将本地内存大小说明为基于G80和G200的GPU的16kB / CU。 对于基于Fermi的卡(GF100),有64kB的片上内存可用,可以配置为48kB本地内存和16kB L1缓存或16kB本地内存和48kB L1缓存。 此外,基于Fermi的卡具有高达768kB的L2缓存(768kB适用于GF100和GF110,512kB适用于GF104和GF114,384kB适用于GF106和GF116,根据维基百科,GF108和GF118没有)。
  3. 从上述信息来看,目前的NVIDIA显卡具有每个计算单元最多的本地内存。 此外,就我所知,它是唯一一个具有通用L2缓存的显卡。

对于您使用本地内存的情况,您应该记住,本地内存是按工作组分配的(并且仅对工作组可访问),而计算单元通常可以支持多个工作组。 因此,如果您的算法将整个本地内存分配给一个工作组,则无法实现最大并行度。 还请注意,由于本地内存是分行随机访问的,因此会导致很多银行冲突和瓶颈序列化。 因此,您的算法可能不会像您认为的那样并行化(或者可能会,并提到了这种可能性)。

对于基于Fermi的卡,如果所有工作组都在同一数据上操作,则最好依靠缓存而不是显式本地内存(尽管我不知道如何切换L1 /本地内存配置)。


你提出的观点非常有趣,我的算法确实在每个计算单元上消耗了所有本地内存。应该有多少个工作组在同一个计算单元上运行才能使其以(接近)全速运行? - user1111929
对我上面第一条评论的补充:每个工作组将包含几百个工作项。 - user1111929
1
@user1111929:基于GF100和GF110的显卡最多有16个CU,因此每个CU有48kB的L2缓存,所以L2的大小与所有L1缓存的总和相同(请记住,L1可以配置为16kB或48kB/CU)。如果所有工作组都在大致相同的数据集上操作,则这将非常有用。对于工作组数量:您需要多少个工作组才能实现最佳速度取决于您的内核。线程越多,延迟就越好隐藏。G80的最大线程/CU为768,G200为1024,GF100为1536,AMD显卡的线程数在1200到3200之间(极低端为6200),具体取决于显卡型号。 - Grizzly
1
根据我上面链接的文档,应该将卡片的定位放在生成(而不是生成的过程中)。对于NVIDIA,我通常尝试使用至少该值的一半,大约为1200左右的高端显卡的最大值,这通常足以隐藏大多数延迟。请注意,线程(因此工作组)的数量也受每个线程使用的寄存器数量和每个CU可用的数量的限制。当然,如果你的工作组足够大,你可能可以只使用一个工作组。 - Grizzly
@Chinasaur:根据编程指南,只有从常量内存中读取和纹理访问才会被缓存,因此它不是一个完整的缓存,它缓存了所有数据访问。虽然这可能已经在gcn(Radeon 7xxx系列)中发生了改变,但我不确定。不知道OP要使用的算法,我不得不假设需要修改对本地内存(或缓存内存)的访问。你说的缓存内存不能被编程,这是什么意思?像任何缓存一样,当访问使用它们的数据时,它们会被隐式使用,所以诀窍是找到最大化缓存重用的使用模式。 - Grizzly
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接