CUDA编程:内存访问速度和内存使用情况:线程局部变量与共享内存变量与数字文字?

时间:2017-04-07 14:34:31

标签: c++ memory cuda

假设我有一个具有多个固定数值的数组,这些数值可以被同一个块中的多个线程多次访问,如果我将这些值存储在以下内容中,在访问速度和内存使用方面有哪些优缺点:

  1. 线程本地内存:double x[3] = {1,2,3};

  2. 共享内存:__shared__ double x[3] = {1,2,3};

  3. 数字文字:直接在表达式中将这些值硬编码

  4. 谢谢!

1 个答案:

答案 0 :(得分:1)

<强> TL; DR

使用__constant__ double x[3]; // ... initialization ...

首先,知道变量实际存在的位置

在你的问题中:

  
      
  1. 线程本地内存:double x [3] = {1,2,3};
  2.   

这是不精确的。取决于您的代码访问x[]x[]如何驻留在寄存器或本地内存中。

由于没有类型限定符,编译器将尽力将事物置于寄存器中,

  

在本节中描述的没有任何__device __,__ shared_和__constant__限定符的设备代码中声明的自动变量通常位于寄存器中。但是在某些情况下,编译器可能会选择将其放在本地内存中,

但是当它不能时,它会将它们放在本地内存

  
      
  • 无法确定是否使用常量进行索引的数组

  •   
  • 会消耗太多寄存器空间的大型结构或数组,

  •   
  • 如果内核使用的寄存器多于可用寄存器,则任何变量(这也称为寄存器溢出)。

  •   

你真的不希望x本地内存中,它很慢。在你的情况下,

  

具有多个固定数值的数组,可由同一块中的多个线程多次访问

__constant____shared__都是不错的选择。

有关此主题的完整说明,请查看:CUDA Toolkit Documentation: variable-type-qualifiers

然后,考虑速度&amp;可用性

<强>硬编码

该号码将嵌入指令中。您可能会期待一些性能提升。在执行此操作之前和之后,请更好地对程序进行基准测试。

<强>注册

它很快,但很少。考虑一个16x16线程的块,每个块最多64k个寄存器,每个线程可以使用256个寄存器。 (好吧,也许不是那么稀缺,应该足够大多数内核)

本地记忆

这很慢。但是,一个线程最多可以使用512KB的本地内存。

  

本地内存空间驻留在设备内存中,因此本地内存访问具有与全局内存访问相同的高延迟和低带宽...

共享内存

它很快,但很少。通常每块48KB(少于寄存器!)。

  

因为它是片上的,所以共享内存比本地或全局内存具有更高的带宽和更低的延迟。

常量记忆

它以不同的方式快速发生(见下文),这在很大程度上取决于缓存,缓存很少。通常每个多处理器有8KB~10KB的缓存。

  

常量内存空间驻留在设备内存中,并缓存在Compute Capability 2.x中提到的常量缓存中。

     

然后将请求拆分为多个单独的请求,因为初始请求中存在不同的内存地址,从而将吞吐量降低了等于单独请求数量的因素。

     

然后,在高速缓存命中的情况下,或者在设备内存的吞吐量下,以恒定高速缓存的吞吐量为结果请求提供服务。

阅读:CUDA Toolkit Documentation: device-memory-accesses