我正在处理一个CUDA共享内存访问模式,我不确定它是好还是有某种性能损失。
假设共享内存中有512个整数
__shared__ int snums[516];
和一半线程,即256个线程。
内核的工作原理如下; (1)256个线程的块首先将函数f(x)应用于snums []的偶数位置,然后(2)将f(x)应用于snums []的奇数位置。函数f(x)作用于给定数字x的局部邻域,然后将x改变为新值。在(1)和(2)之间有一个__syncthreads()。
显然,在我做(1)的时候,由于没有被访问的奇数,所以存在32位的共享存储器间隙。在(2)中也是如此,在snums []的偶数位置上会有间隙。
根据我在CUDA文档中读到的内容,当线程访问相同位置时,应该发生内存库冲突。但他们没有谈论差距。
银行是否会出现任何可能导致性能下降的问题?
答案 0 :(得分:2)
我猜你的意思是:
__shared__ int snums[512];
是否会出现银行冲突和性能损失?
假设您的代码在某些时候执行类似的操作:
int a = snums[2*threadIdx.x]; // this would access every even location
上面的代码行将生成具有双向库冲突的访问模式。双向存储体冲突意味着上面的代码行执行的时间大约是最佳无库冲突代码行的两倍(如下所示)。
如果我们只关注上面的代码行,消除银行冲突的明显方法是重新排序共享内存中的存储模式,以便之前存储在{{1}的所有数据项},snums[0]
,snums[2]
...现已存储在snums[4]
,snums[0]
,snums[1]
...因此有效地移动了"偶数&# 34;数组开头的项目和" odd"项目到数组的末尾。这将允许像这样的访问:
snums[2]
但是你已经声明计算邻域很重要:
函数f(x)作用于给定数字x的本地邻域,...
因此,这种重组可能需要一些特殊的索引算法。
在较新的体系结构中,当线程访问相同位置时,不会发生共享内存库冲突,但如果它们访问同一个库中的位置,则会发生共享内存库冲突是不一样的位置)。该存储区只是32位索引地址的最低位:
int a = snums[threadIdx.x]; // no bank conflicts
(以上假定为32位存储模式) This answer也可能是有意义的