检查这一点的最佳方法是使用“Compute Visual Profiler”来分析您的代码;这与 CUDA 工具包一起提供。GPU Gems 3中也有一个很棒的部分- “39.2.3 Avoiding Bank Conflicts”。
“当同一个warp中的多个线程访问同一个bank时,除非warp的所有线程访问同一个32位字内的相同地址,否则会发生bank冲突” - 首先有16个内存bank,每个4bytes宽。所以本质上,如果你有任何线程在半扭曲中从共享内存库中的相同 4 字节读取内存,你将遇到银行冲突和序列化等。
好的,你的第一个例子:
首先让我们假设您的数组例如是int类型(一个 32 位字)。您的代码将这些整数保存到共享内存中,跨过任何半扭曲,第 K 个线程正在保存到第 K 个内存库。因此,例如前半束的线程 0 将保存到shared_a[0]
第一个内存组中的哪个,线程 1 将保存到shared_a[1]
,每个半束有 16 个线程,这些线程映射到 16 个 4 字节组。在接下来的半个 warp 中,第一个线程现在将其值保存到 shared_a[16] 中,这是第一个再次记忆库。因此,如果您使用 4 字节字,例如 int、float 等,那么您的第一个示例不会导致银行冲突。如果您使用 1 字节的字,例如 char,则在前半部分 warp 线程 0、1、2 和 3 都会将它们的值保存到共享内存的第一组,这将导致组冲突。
第二个例子:
同样,这完全取决于您使用的单词的大小,但对于示例,我将使用 4 字节的单词。所以看看前半个经线:
线程数 = 32
N = 64
线程 0:将写入 0、31、63 线程 1:将写入 1、32
跨半扭曲的所有线程同时执行,因此对共享内存的写入不应导致银行冲突。不过,我必须仔细检查一下。
希望这会有所帮助,很抱歉回复了这么多!