【问题标题】:Shared memory bank conflicts, multicast and broadcast performance Cuda共享内存库冲突、多播和广播性能 Cuda
【发布时间】:2014-07-16 17:17:47
【问题描述】:

我了解,对于 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.组播:18 毫秒 2.广播:9毫秒 3.线性:5.5ms 4.银行冲突:90ms

我希望无银行冲突的代码会表现得类似。为什么广播、多播和线性访问之间存在差异?

干杯, T

(问题随后被编辑,因为原始版本被标记为过于宽泛)

【问题讨论】:

标签: cuda multicast broadcast


【解决方案1】:

如果我们有这样的共享内存定义:

__shared__ int sdata[BLOCK_SIZE*2];

以下代码行将生成代表here(中间列)的银行访问模式,没有银行冲突:

int a = sdata[2*(threadIdx.x%16)];

以下代码行将生成相同的银行访问模式(尽管位置不同),但存在 2 路银行冲突:

int a = sdata[2*threadIdx.x];

【讨论】:

  • 谢谢,这两个答案都非常有帮助。只是想知道,开普勒设备(功能 3.0)如何发生银行冲突?
  • 它的发生方式与任何其他设备基本相同。两个或多个线程正在从共享内存中具有相同存储库的不同位置请求数据。 SO上有很多问题可以解释并举例说明银行冲突。在大多数情况下,Kepler 的行为与 Fermi 相同,尤其是在 32 位 bank 模式下。
  • 感谢 cmets,他们真的很有帮助
猜你喜欢
  • 2015-04-07
  • 1970-01-01
  • 2011-05-22
  • 1970-01-01
  • 1970-01-01
  • 2021-01-19
  • 2021-11-07
  • 2012-06-26
  • 1970-01-01
相关资源
最近更新 更多