假设我有一个具有多个固定数值的数组,这些数值可以被同一个块中的多个线程多次访问,如果我将这些值存储在以下内容中,在访问速度和内存使用方面有哪些优缺点:
线程本地内存:double x[3] = {1,2,3};
共享内存:__shared__ double x[3] = {1,2,3};
数字文字:直接在表达式中将这些值硬编码
谢谢!
答案 0 :(得分:1)
<强> TL; DR 强>
使用__constant__ double x[3]; // ... initialization ...
在你的问题中:
- 线程本地内存:double x [3] = {1,2,3};
醇>
这是不精确的。取决于您的代码访问x[]
,x[]
如何驻留在寄存器或本地内存中。
由于没有类型限定符,编译器将尽力将事物置于寄存器中,
在本节中描述的没有任何__device __,__ shared_和__constant__限定符的设备代码中声明的自动变量通常位于寄存器中。但是在某些情况下,编译器可能会选择将其放在本地内存中,
但是当它不能时,它会将它们放在本地内存:
中
无法确定是否使用常量进行索引的数组
会消耗太多寄存器空间的大型结构或数组,
如果内核使用的寄存器多于可用寄存器,则任何变量(这也称为寄存器溢出)。
你真的不希望x
在本地内存中,它很慢。在你的情况下,
具有多个固定数值的数组,可由同一块中的多个线程多次访问
__constant__
和__shared__
都是不错的选择。
有关此主题的完整说明,请查看:CUDA Toolkit Documentation: variable-type-qualifiers
<强>硬编码强>
该号码将嵌入指令中。您可能会期待一些性能提升。在执行此操作之前和之后,请更好地对程序进行基准测试。
<强>注册强>
它很快,但很少。考虑一个16x16线程的块,每个块最多64k个寄存器,每个线程可以使用256个寄存器。 (好吧,也许不是那么稀缺,应该足够大多数内核)
本地记忆
这很慢。但是,一个线程最多可以使用512KB的本地内存。
本地内存空间驻留在设备内存中,因此本地内存访问具有与全局内存访问相同的高延迟和低带宽...
共享内存
它很快,但很少。通常每块48KB(少于寄存器!)。
因为它是片上的,所以共享内存比本地或全局内存具有更高的带宽和更低的延迟。
常量记忆
它以不同的方式快速发生(见下文),这在很大程度上取决于缓存,缓存很少。通常每个多处理器有8KB~10KB的缓存。
常量内存空间驻留在设备内存中,并缓存在Compute Capability 2.x中提到的常量缓存中。
然后将请求拆分为多个单独的请求,因为初始请求中存在不同的内存地址,从而将吞吐量降低了等于单独请求数量的因素。
然后,在高速缓存命中的情况下,或者在设备内存的吞吐量下,以恒定高速缓存的吞吐量为结果请求提供服务。