共享内存和常量

3

在共享内存中存储常量值是否有任何好处呢?例如:

A[tid] = CONSTANT * B[tid]

其中AB是数组,CONSTANT是一个常量值,例如4,tid是线程索引(数组元素=单个线程)。

每个线程都必须读取值CONSTANT,因此共享内存应该很有用,对吧?

我认为它的工作原理是: 从全局内存中读取数据需要消耗大量时间,因此将常量值从全局内存中读取一次并存储到共享内存中,然后线程可以快速读取它。由于有许多线程(常量值必须被多次读取),因此共享内存应该加速这个过程。

2个回答

4
一些CPU指令集(如x86)支持将完整大小的常量作为操作数与操作码交错存储。在这种情况下,常量显然会随着CPU正在运行的指令流一起读取,因此似乎将它们存储在其他地方不会更快。
其他架构(如ARM)支持在操作码中存储小常量和移位值。程序中通常需要的大多数常量都可以表示为一个小常量加上一个移位值,因此可以直接存储在操作码中。
我不知道SASS(NVIDIA GPU的本地指令集)是否支持这样的“嵌入式”常量。
但是,请考虑如果您将常量存储在共享内存中,则需要引用该常量,该引用本身将是一个常量,或者它将派生自一个常量(例如基地址)。
此外,有一个缓存用于指定为常量的值。您可以通过在调用内核之前在常量内存中设置这些值来利用此缓存。
进一步考虑将常量设置在共享内存中的开销。共享内存中的值只能在块内的线程之间共享,因此每个块都必须再次设置常量。由于线程以32个一组(称为warp)运行,因此每次处理启动新块时,内核将占用32个线程来设置常量。
总之,我认为最好让编译器处理单个常量(如您示例中的常量),并使用常量内存来存储可能存在的任何常量数组。

5
各种GPU指令集都提供了立即数值的编码方式,适用于整数和浮点指令。编译器会尽可能利用这些编码方式来处理编译时的常量。对于无法嵌入到指令中的常量,编译器可以将其放置在常量存储区中,并且这些数据可以被常量缓存缓存,它具有广播特性,可以同时向warp中的所有线程提供相同的常量。因此,对于单个常量,可以简单地依赖编译器。 - njuffa

1

常量内存空间被缓存,读取性能很高。因此,我怀疑将其存储在共享内存中不会有太大的性能差异。


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