第5章 CUDA存储器

第五章 CUDA 存储器

《大规模并行处理器编程实战》学习,其他章节关注专栏 CUDA C

CUDA C 编程友情链接:

线程处理数据时需要先将数据从 host copy 到 device 的全局存储器中,然后利用 block ID 和 thread ID 决定其需要处理的数据位置,从而进行并行计算。kernel 在计算时,需要和存储器(全局存储器)进行大量的互动,这种存储器通常使用动态随机访问存储器(Dynamic Random Access Memory, DRAM),在访问时时延有时会特别大,因此 CUDA 提供了大量访问存储器的方法,这种方法消除了对全局存储器的访问,从而提高访存速度,提高 CUDA kernel 处理速度。

5.1 存储器访问效率的重要性

CGMA(Compute to Global Memory Access)指在 CUDA 程序在某一区域内每次访问全局存储器时,执行浮点运算的次数。CUDA 比值能较准确的体现 CUDA 中 kernel 函数的性能
在这里插入图片描述

此时的 CGMA = 1:1 = 1.0

当全局存储器的带宽是 200GB/s,单精度浮点数为4字节,则单精度浮点数的读带宽为 200GB/4B = 50 GFLOPS,当 CGMA = 1.0 时,则单精度浮点数的操作不能超过 50 GFLOPS。

5.2 CUDA 设备存储器的类型

在这里插入图片描述
在这里插入图片描述

  • 全局存储器(主机交互)
  • 常数存储器(只读)
  • 寄存器和共享存储器,即片上存储器寄存器只能被单个线程访问,共享存储器可以被线程块中的所有线程访问。

两种不同处理架构

在这里插入图片描述在这里插入图片描述

不同变量在定义其作用域的时候,有不同的声明方法:在这里插入图片描述

注:自动数组变量存储在全局存储器中

5.3 减少全局存储器流量的一种策略

全局存储器访问慢,而共享存储器访问快。将数据划分为多个子集,称为块(tile),进行块的存取,减少访存(全局)次数,提高效率。
对经常访问全局存储器点可以驻留在片上存储器中,可以减少访全局存,但过多的驻留会导致片上存储器被大量占用,因此需要用栅栏同步进行同步,减少驻留时间。

5.4 分块矩阵乘法的 kernel 函数

对于原始的矩阵乘法,可以进行分步运算。
对于每一阶段,

  1. 每个线程先从全局存储器取所需块数据到共享存储器,每1个线程取2个位置(以2*2大小为单元进行矩阵乘);
  2. 将取得数据进行sum of product积之和运算,得到此2*2单元的矩阵乘积。
  3. 如图,红色表示 P 0 , 0 P_{0,0} P0,0线程的操作,将红色区域进行积之和,其取 M 0 , 0 M_{0,0} M0,0 M 0 , 1 M_{0,1} M0,1的数据,N矩阵的取值交给紫色。其他颜色同理,因为同一数据M或N同时被2*2范围内的两个线程使用,因此由两个线程在同一阶段进行分别取值,共享数据。

在这里插入图片描述

[在这里插入图片描述
在这里插入图片描述

5.5 存储器——限制并行性的一个因素

每个SM中能分配的寄存器和共享存储器都是有限的,且是以线程块为单位进行分配的。若可容纳线程块*所需寄存器/存储器每块>SM的最大容量,则会以块为单位较少每个SM中的运行线程块数量。若存储器/寄存器可容纳线程数大于SM的最大容纳线程数,则SM的固有最大线程数成为了限制速度的因素。
编程时根据获取的硬件信息,动态的确定共享存储器的使用量,可以提高GPU利用率,加速计算。因此对矩阵乘法中的共享寄存器声明进行修改:
在这里插入图片描述
在启动Kernel时,也能进行存储器大小设定:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_40491305/article/details/116236291