transpose
参考链接
方法一:每个线程负责一个元素的转置
- cuda代码实现
- ncu分析(矩阵维度采用m=1024,n=512;grid和block维度见下图最上方)
这种方法对读global mem比较友好,可以做到合并访存,但对写global mem就非常不友好,通过ncu分析拿到相关指标可以证明这一点,下图是 ncu --section MemoryWorkloadAnalysis_Tables
-
先说明一下nVidia gpu的cache的读写策略
- cache读策略:l1和l2,l2和HBM之间都是以sector为单位读取的
- cache写策略:l1和l2之间采用write-through & not write-allocate;l2和HBM之间采用write-back &write-allocate。对于write-allocate要注意一点,如果某个来自l2 cache的store request刚好写一个sector那么就不需要把这个sector从HBM中先读到l2 cache(因为读了也是白读,这块sector全部要被写入),如果该request要写的sector中有些字节没写到,那么就需要先把该sector读到l2 cache再写l2 cache。
-
分析各级load
-
L1 Cache的Global Load
- Requests
表示warp对L1 cache发送的Global Load请求条数,warp中32个线程对L1发送的Global Load指令会被合并成一个Request再发给L1(应该是LSU做的),一共有16 * 128 * 32 * 8/32=16384个warp,分析cuda代码可知每个warp都会产生一个Request,所以一共有16384个Request。 - Sector
表示L1传输给warp的总Sector数(一个Sector32字节),由于warp中32个线程各自的load可以发生合并访存,每个线程请求读4字节,所以warp发送的一个Load Request中恰好包含4个sector,所以总sector个数=16384 * 4=65536 - Hit Rate
表示load 请求的命中率,最开始l1 cache中无任何数据的缓存,所以命令率是0 - Sector Misses to L2
表示发给L2的sector请求(warp向L1发送的sector请求miss了所以要发给l2),这里全部没有命中,所以sector请求全部发给l2了,即65536个sector请求
- Requests
-
L2 Cache的 L1/TEX Load
- Sectors
表示L1发给L2的sector请求个数,就等于Sector Misses to L2,即65536 - Hit Rate
表示load 请求的命中率,最开始l2 cache中无任何数据的缓存,所以命令率是0 - Sector Misses to Device
表示发给HBM的sector请求个数,这里也是全部没有命中,所以sector请求全部发给HBM了,即65536个sector请求
- Sectors
-
Device Memory的 Load
- Sectors
表示从HBM读取到l2的sector个数,图中是66353(比65536多一点,应该是会读取其他的一些数据?目前不是很清楚)
- Sectors
-
-
分析各级store
-
L1 Cache的Global Store
- Requests
表示warp对L1 cache发送的Global Store请求条数,计算方式同Global Load一样是,一共有16384个Request - Sectors
表示warp对L1 cache发送的Global Store请求条数,由于warp中32个线程各自的store不能发生合并访存,每个线程请求写4字节,但相邻id的线程写的字节并不能拼到一个sector中,所以每个线程都得单独给l1 cache发一个sector (虽然这个sector只包含4个字节是该线程真正要写回global mem的),所以warp发送的一个Store Request中包含32个store sector请求,所以总sector个数=warp数*32=16384 * 32=524288(图中是524316多了一点,emmm,反正差不多) - Hit Rate
暂时没弄懂store的hit rate是怎么算的 - Sector Misses to L2
表示发给L2的sector的store请求,l1和l2之间采用的是write-through & not write-allocate,所以l1接收到写sector的请求后会全发给l2,这里总共是524288个sector
- Requests
-
L2 Cache的L1/TEX Store
- Sectors
表示来自l1的写sector个数,524288 - Hit Rate
暂时没弄懂store的hit rate是怎么算的 - Sector Misses to Device
表示发给HBM的sector请求个数,l2和HBM之间采用的是write-back & write-allocate,所以l2接收到写sector的请求后并不会直接发给HBM,而是等cacheline被evict后才真正写回HBM,所以Sector Misses to Device是0
- Sectors
-
Device Memory的Store
- Sectors
这里只看到很小一点的sector被写入HBM(1063),原因还是刚刚分析的,l2和HBM之间采用的是write-back & write-allocate,所以l2接收到写sector的请求后并不会直接发给HBM,而是等cacheline被evict后才真正写回HBM。 这里由于我的代码逻辑是执行完转置kernel函数后直接退出程序了,所以后面没有其他的kernel函数读数据来evict掉l2 cache的数据,所以这里ncu分析到的只有一点sector被写入HBM(应该是transposs kernel函数自己evict掉的一小部分cacheline)
- Sectors
-
-
方法二:每个线程负责4*4的小矩阵转置
TODO