扭曲线程不是 SIMD 同步的
Warp threads not SIMD synchronous
我正在进行并行缩减 example from Nvidia。如果 tid < 32
那么线程都应该在同一个 warp 中,所以指令应该是 SIMD 同步的,所以我们可以假设 sdata[tid] += sdata[tid + 32];
在 sdata[tid] += sdata[tid + 16];
之前为所有线程完成并且很快。但这对我来说并没有发生。
for (unsigned int s=groupDim_x/2; s>32; s>>=1)
{
if (tid < s) sdata[tid] += sdata[tid + s];
GroupMemoryBarrierWithGroupSync();
}
if (tid < 32)
{
sdata[tid] += sdata[tid + 32];
sdata[tid] += sdata[tid + 16];
sdata[tid] += sdata[tid + 8];
sdata[tid] += sdata[tid + 4];
sdata[tid] += sdata[tid + 2];
sdata[tid] += sdata[tid + 1];
}
Cuda 上相同问题的解决方案已经发布 (),但它使用指针和 volatile 关键字。 Directcompute 没有指针,也不允许在全局内存上使用 volatile 关键字。
Directcompute doesn't have pointers and doesn't allow the volatile keyword on global memory.
的确如此,但它公开了与内部函数相当的功能。将循环中的 +=
替换为 InterlockedAdd
intrinsic function,看看会发生什么。但是该函数仅适用于整数。
我正在进行并行缩减 example from Nvidia。如果 tid < 32
那么线程都应该在同一个 warp 中,所以指令应该是 SIMD 同步的,所以我们可以假设 sdata[tid] += sdata[tid + 32];
在 sdata[tid] += sdata[tid + 16];
之前为所有线程完成并且很快。但这对我来说并没有发生。
for (unsigned int s=groupDim_x/2; s>32; s>>=1)
{
if (tid < s) sdata[tid] += sdata[tid + s];
GroupMemoryBarrierWithGroupSync();
}
if (tid < 32)
{
sdata[tid] += sdata[tid + 32];
sdata[tid] += sdata[tid + 16];
sdata[tid] += sdata[tid + 8];
sdata[tid] += sdata[tid + 4];
sdata[tid] += sdata[tid + 2];
sdata[tid] += sdata[tid + 1];
}
Cuda 上相同问题的解决方案已经发布 (
Directcompute doesn't have pointers and doesn't allow the volatile keyword on global memory.
的确如此,但它公开了与内部函数相当的功能。将循环中的 +=
替换为 InterlockedAdd
intrinsic function,看看会发生什么。但是该函数仅适用于整数。