1

如果每个 warp 访问同一地址的共享内存,那将如何加载 32 字节的数据(ulong4)?会被“广播”吗?访问时间是否与每个线程加载 2 个字节的“无符号短整数”相同?

现在,如果我需要在每个扭曲中从共享内存中加载 32/64 相同的字节,我该怎么做呢?

4

1 回答 1

1

在计算能力 3.0 之前的设备上,共享内存访问始终为 32 位/4 字节宽,并且如果一个 warp 的所有线程访问相同的地址,将被广播。更广泛的访问将编译为多个指令。

在计算能力 3.0 共享内存访问可以使用 cudaDeviceSetSharedMemConfig() 配置为 32 位宽或 64 位宽。不过,所选设置将应用于整个内核。


[由于我最初错过了问题中的“共享”这个小词,因此我对全局内存给出了一个完全跑题的答案。既然那个应该仍然是正确的,我就把它留在这里:]

这取决于:

  • 计算能力 1.0 和 1.1 不广播并使用 64 个单独的 32 字节内存事务(两次 16 字节,扩展为每个线程的最小 32 字节事务大小)
  • 计算能力 1.2 和 1.3 广播,因此两个 32 字节事务(两次 16 字节,扩展到最小 32 字节事务大小)足以满足 warp 的所有线程
  • 计算能力 2.0 及更高版本只需读取 128 字节缓存行并满足来自那里的所有请求。

计算能力 1.x 的设备将浪费 50% 的传输数据,因为单个线程最多可以加载 16 字节,但最小事务大小为 32 字节。此外,32 字节事务比 128 字节事务慢得多。

由于最小事务大小,并且数据路径足够宽,可以在每个事务中向每个线程传输 8 或 16 个字节,时间将与每个线程仅读取 8 个字节相同。

在计算能力 1.x 上读取 2 倍或 4 倍的数据将花费 2 倍或 4 倍的时间,但如果数据落入同一缓存行,则在 2.0 和更高版本上只需要最少的时间,因此不需要进一步的内存事务。

因此,在计算能力 2.0 及更高版本上,您无需担心。在 1.x 上,如果数据是常量,则通过常量缓存或纹理读取数据,否则在共享内存中重新排序(假设您的内核受内存带宽限制)。

于 2012-09-26T21:40:57.533 回答