CUDA总结:共享内存

共享内存是片上内存(on-chip),所以速度比一般的显存快很多,如(全局内存、常亮内存、纹理内存)。共享内存是gpu中,带宽仅次于寄存器的存储器。

共享内存是有限的,与L1 Cache公用一块on-chip内存,用户可以调整L1 cache与共享内存的大小组合。

在on-chip内存的基础上,共享内存还实现了“并行访存”:共享内存被划分为大小相等的n个部分(每个部分称为一个bank),同一时刻的n个访存请求将分别通过这n个部分进行,从而使共享内存的带宽变为n倍!

当然,n倍带宽是最佳情况,如果这n个访存请求中存在对相同bank的请求,那么相同的请求将变为串行的,即排队进行。如果n个请求均是相同bank的,那么这n个请求就要串行执行,只能获得1倍带宽。这种现象称为bank conflict(bank冲突)

bank 冲突有一种特殊情况,即来自同一个warp内的线程对共享内存同一地址的访存请求,不会产生bank冲突!假设极端情况:32个线程均访问同一个内存地址,那么,当访存请求为读操作时,该地址的数据会被广播至32个线程;当写操作时,这32个线程中的其中一个线程会该地址写入数据,至于哪一个线程是不确定的!
其实,bank冲突就是一种data race现象,bank就是临界区,不同thread对相同bank的访问就会产生race,gpu为了防止这种情况的发生,强行让这些访问串行化。
对于来自不同warp的bank冲突不会造成严重的latency,可以忽略

假设,通过共享内存访问float类型的数据:
bank0~bank31 0 1 2 … 30 31
bank0~bank31 32 33 34 … 62 63
(由于一个bank的带宽为32bit,所以一个float数据占用一个bank;而目前设备的共享内存拥有32个bank,即0~31个数据属于bank0~bank31,第32个数据开始又重新从bank0开始缓存)
执行以下操作:

 float value = share_mem[tid];

同一个warp中的32个线程
t0:0、t1:1、t2:2 … t31:31
以上的访存过程不会产生bank冲突,因为同一个warp每个线程的访存落在了不同的bank

但如果执行以下操作:

float value = share_mem[tid*4];

同一个warp中的32个线程
t0:0、t1:4、t2:8 、t3:12、t4:16 、t5:20、t6:24、t7:28
t8:32 …
t16:64 …
t24:96 …
这就会导致bank冲突,其中,t0、t8、t16、t24落在了同一个bank的不同内存地址了!共享内存在没有bank冲突的情况下,带宽与寄存器相近,也是1个cycle;但该情况下,带宽下降为原来的1/4,因为每一时刻每个bank都有4个线程在排队,只能同时读取32/4=8个数据,要4个cycle才能读取完32个数据

bank冲突最严重的情况:

float value = share_mem[tid*32];

t0:0
t1:32
t2:64

同一个warp内所有线程都产生bank冲突!此时共享内存的带宽下降为1/32,要32个cycle才能读取完32个数据

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值