如果每个 warp 访问同一地址的共享内存,那将如何加载 32 字节的数据(ulong4)?会被“广播”吗?访问时间是否与每个线程加载 2 个字节的“无符号短整数”相同?
现在,如果我需要在每个扭曲中从共享内存中加载 32/64 相同的字节,我该怎么做呢?
在计算能力 3.0 之前的设备上,共享内存访问始终为 32 位/4 字节宽,并且如果一个 warp 的所有线程访问相同的地址,将被广播。更广泛的访问将编译为多个指令。
在计算能力 3.0 共享内存访问可以使用 cudaDeviceSetSharedMemConfig() 配置为 32 位宽或 64 位宽。不过,所选设置将应用于整个内核。
[由于我最初错过了问题中的“共享”这个小词,因此我对全局内存给出了一个完全跑题的答案。既然那个应该仍然是正确的,我就把它留在这里:]
这取决于:
计算能力 1.x 的设备将浪费 50% 的传输数据,因为单个线程最多可以加载 16 字节,但最小事务大小为 32 字节。此外,32 字节事务比 128 字节事务慢得多。
由于最小事务大小,并且数据路径足够宽,可以在每个事务中向每个线程传输 8 或 16 个字节,时间将与每个线程仅读取 8 个字节相同。
在计算能力 1.x 上读取 2 倍或 4 倍的数据将花费 2 倍或 4 倍的时间,但如果数据落入同一缓存行,则在 2.0 和更高版本上只需要最少的时间,因此不需要进一步的内存事务。
因此,在计算能力 2.0 及更高版本上,您无需担心。在 1.x 上,如果数据是常量,则通过常量缓存或纹理读取数据,否则在共享内存中重新排序(假设您的内核受内存带宽限制)。