技术开发 频道

了解和使用共享内存(一)

  从前面的讨论中我们可以得出以下几点有用信息:

  • 多处理器资源如共享内存是有限的、宝贵的。
  • 为一系列支持CUDA的设备配置,有效管理有限的多处理器资源(如共享内存),已经成为CUDA开发人员日常生活的一部分。
  • 请注意条件操作(例如,if语句)对内核的运行有深刻影响。
  • CUDA使用率计算工具和nvcc编译器是值得我们学习和使用的重要工具――尤其在探索执行配置时。

  CUDA内存模型

  在设备中执行的线程可以通过下图展示的内存类型来访问全局内存和芯片内存:

  每个多处理器,见上图的块(0, 0)和块(1, 0),均包含以下四种内存类型:

  1. 每线程一组本地寄存器。
  2. 一个并行数据缓存或共享内存。被所有线程共享;能实现共享内存空间。
  3. 一个只读的常量缓存。被所有线程共享;能加快读取常量内存空间的速度;被实现为设备内存的只读区(在后面的专栏中将介绍常量内存。在那之前,如需更多信息,请参阅CUDA编程指南的第5.1.2.2节)。
  4. 一个只读的纹理缓存。被所有处理器共享;能加快读取纹理内存空间的速度;被实现为设备内存的只读区(在后面的专栏中将介绍纹理内存。在那之前,如需更多信息,请参见CUDA编程指南的第5.1.2.3节)。

  不要被上图中的多处理器中标有“本地内存”的块所迷惑。“本地内存”指的是每个线程范围内的本地内存。它是一个内存抽象,而不是多处理器的实际硬件组件。实际上,本地内存由编译器在全局内存中分配,与其他全局内存区提供的性能相同。本地内存基本上被编译器用来保存一些程序员视为线程本地的而又由于某种原因不适合保存到速度更快的内存中的信息。通常在内核中声明的自动变量驻留在提供快速访问的寄存器中。在某些情况下,编译器可能选择在本地内存中存放这些变量,其中一种情况就是寄存器变量太多,一个数组包含四个以上元素,某些结构或数组会消耗太多的寄存器空间,另外一种情况就是编译器不能确定一个数组是否通过恒量进行索引。

  请谨慎使用,因为本地内存可能会降低性能。检查ptx汇编代码(可以通过编译–ptx或-keep选项获得)可以知道一个变量是否在最初编译阶段被放置在本地内存,因为变量是通过.local助记符来声明的,是通过ld.local和st.local助记符来访问的。如果在最初阶段没有将它放置到本地内存,那么在随后的编译阶段如果发现它可能会消耗目标架构太多的寄存器空间也可能会决定将它放置在那里。

  在阅读下一期之前,我建议利用使用率计算工具来深入了解执行模性和内核启动执行配置对寄存器和共享内存的数量有什么影响。

  改变共享内存的数量会影响可用寄存器的数量吗?

   如何取得活动块数量和可用多处理器资源之间的平衡?

  其他资源

  CUDA使用率计算工具: http://developer.download.nvidia.com/compute/CUDA/CUDA_occupancy_calculator.xls

     CUDA编程指南:在CUDA区http://www.nvidia.com/CUDA的“文档”部分。

1
相关文章