繁体   English   中英

了解CUDA shfl指令

[英]Understanding CUDA shfl instruction

我已经阅读了Shuffle Tips and Tricks的文章,但不确定如何将其应用于继承的一些易懂的代码:

extern __shared__ unsigned int lpSharedMem[];
int tid = threadIdx.x;
lpSharedMem[tid] = startValue;
volatile unsigned int *srt = lpSharedMem;

// ...various stuff
srt[tid] = min( srt[tid], srt[tid+32] );
srt[tid] = min( srt[tid], srt[tid+16] );
srt[tid] = min( srt[tid], srt[tid+8] );
srt[tid] = min( srt[tid], srt[tid+4] );
srt[tid] = min( srt[tid], srt[tid+2] );
srt[tid] = min( srt[tid], srt[tid+1] );
__syncthreads();

即使没有CUDA,此代码也相当狡猾,但查看此实现,我会看到:

__device__ inline int min_warp(int val) {
    val = min(val, __shfl_xor(val, 16));
    val = min(val, __shfl_xor(val, 8));
    val = min(val, __shfl_xor(val, 4));
    val = min(val, __shfl_xor(val, 2));
    val = min(val, __shfl_xor(val, 1));
    return __shfl(val, 0);
}

此代码可通过以下方式调用:

int minVal = min_warp(startValue);

因此,我可以用上面的代码替换我那狡猾的volatile 但是,我无法真正理解发生了什么。 有人可以解释我是否正确,以及min_warp()函数中到底发生了什么。

int __shfl_xor(int var, int laneMask, int width=warpSize);

__shfl_xor()通过对调用者的通道ID与laneMask进行按位XOR运算来计算源行ID:返回由所得通道ID保持的var值。 (...)

通道ID是线程束中从0到31的线程索引。因此,硬件会对每个线程执行按位XOR:sourceLaneId XOR laneMask => destinationLaneId

例如,使用线程0和:

__shfl_xor(val, 16)

laneMask = 0b00000000000000000000000000010000 = 16(十进制)

srclaneID = 0b00000000000000000000000000000000 = 0(十进制)

XOR ------------------------------------------------- ---------

dstLaneID = 0b0000000000000000000000000001000010000 = 16(十进制)

然后线程0获得线程16的值。

现在使用线程4:

laneMask = 0b00000000000000000000000000010000 = 16(十进制)

srclaneID = 0b00000000000000000000000000000100 = 4(十进制)

XOR ------------------------------------------------- ---------

dstLaneID = 0b00000000000000000000000000000000010100 = 20(十进制)

因此,线程4获得线程20的值。

如果我们回到实际的算法,我们会看到这是应用min运算符的并行约简。 在步骤:

  1. 32个线程将其值累加到较低的16个线程中。
  2. 16个线程累加到较低的8个线程中。 (其他线程与实际算法无关紧要)
  3. 8个线程累加到较低的4个线程中。
  4. 4个线程累加到下面2个线程中...

PD:请注意,两个代码并不完全相同。 此偏移量“ 32”告诉我们您的共享内存阵列的长度为2 * WARP。 (您正在将2 * WARP值减少为1)

srt[tid] = min( srt[tid], srt[tid+32] );

洗牌一将WARP值减小为1。

这些幻灯片在第27页上有一个直观的图表,如下所示:

http://on-demand.gputechconf.com/gtc/2017/presentation/s7622-Kyrylo-perelygin-robust-and-scalable-cuda.pdf

xor 1首先交换奇/偶单输入

xor 2然后交换奇数/偶数对先前交换的输入

xor 4然后交换奇/偶四边形

等等

另一种方法是计算一个完整的“异或”掩码和原始输入值的“异或”值。 有多种方法可以使用不同的经纱混洗指令来完成此操作。 此异或模式也用于FFT / DFT转换,也称为“蝴蝶图”。

https://zh.wikipedia.org/wiki/蝴蝶图

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM