1. Shared Memory
可以知道的是,我们在GPU中执行Cuda线程程序中,应该尽可能减少从Global Memory中进行访存操作。原因是,这会大大降低线程执行的效率。Global Memory数据是存储在公共显存中,但是每一个线程是在一个SP单元中执行,从公共显存到执行单元,这样数据的传输效率会比较低。如果在Block内的共有空间访问数据,即在Shared Memory中读取数据,就会快很多。因此,CUDA编程优化的一个重要点,就是要利用Shared Memory来在访存上提升效率。
以矩阵相乘为例,我们希望把矩阵中的一个区域,按照一个块提前读取到Shared Memory中,然后进行计算。
程序按照不同的Block进行读取
这里需要注意的是,shared memory是定义在block上,因此一个block中的线程是共享shared memory的。
定义Shared Memory空间需要注意的是:
这里的TILE_WIDTH的数值是与Shared Memory空间相对应,执行的时候,因为是多线程并行执行,所以自然会收到单block内Thread上限数量的限制,如下所示:
因为减少了从Global到执行单元的数据传输次数,所以程序提升了执行效率。
2. 并行规约
求和
通过修改线程索引方式,实现在减少线程的情况下,实现同样的功能:
八个线程的累加:
四个线程的累加:
3. Wrap分割
一个block中,32个线程组成一个Wrap,作为一个基本的调度单元。
一个Warp内部的线程需要保持步调一致。下列情况会产生分支:
应该尽量避免这种情况。
从Warp优化的角度上看, 并行规约的第二种情况warp优化的情况会更好。