据我所知,对于Kepler设备(cc 3.0)及以上共享内存冲突仅在来自同一warp的线程访问同一个bank中的不同字时才会发生。如果所有线程都访问同一个字(广播)或某些线程访问银行中的同一个字(多播),则没有冲突。
在以下代码中:
__shared__ float3 nodeCoefficient[sideX * sideY * sideZ];
...
for (unsigned int zIdx = 0; zIdx < 4; zIdx++) {
for (unsigned int yIdx = 0; yIdx < 4; yIdx++) {
for (unsigned int xIdx = 0; xIdx < 4; ++xIdx) {
int indexXYZ = ((threadidx.z/5.5 + zIdx) * sideY + (threadidx.y/5.5+ yIdx)) * sideX + (threadidx.x/5.5 + xIdx);
displace += nodeCoefficient[indexXYZ] * (bValues[xIdx].x * bValues[yIdx].y);
}
}
}
共享内存访问中存在多播
现在,如果我们将indexXYZ更改为:
indexXYZ = (( zIdx) * sideY + ( yIdx)) * sideX + ( xIdx);
我们有广播。
最后,如果我们将indexXYZ更改为:
int indexXYZ = ((threadidx.z + zIdx) * sideY + (threadidx.y+ yIdx)) * sideX + (threadidx.x + xIdx);
我们有线性访问模式。
以上的性能比较,包括故意的银行冲突版本,如下所示:gtx750m:
1.Multicast:18毫秒 2.播放:9毫秒 3.线性:5.5ms 4.银行冲突:90毫秒
我希望银行无冲突代码的行为类似。为什么广播,多播和线性访问之间存在差异?
干杯, Ť
(随后对该问题进行了编辑,因为原始版本被标记为过于宽泛)
答案 0 :(得分:1)
如果我们有这样的共享内存定义:
__shared__ int sdata[BLOCK_SIZE*2];
以下代码行将生成代表here(中间列)的银行访问模式,没有银行冲突:
int a = sdata[2*(threadIdx.x%16)];
以下代码行将生成具有双向银行冲突的相同银行访问模式(尽管位于不同的位置):
int a = sdata[2*threadIdx.x];