cuda parallel reduction with shared memory

参考文献:https://developer.download.nvidia.cn/assets/cuda/files/reduction.pdf

文中对Scalar Reduction提出了6阶段的优化方法,其中比较关键的思想如下:

1.Avoid warp divergent

2.Sequential addressing is conflict free(连续寻址消除bank conflict)

3.Unroll the last warp(即warpReduce,这里要注意volatile关键字的作用,如果warpReduce的参数必须声明为volatile类型的)

4.Use Template to unroll all loop && avoid conditional statement(if .. else..)

5.Multiple Adds(就是在对shared_data做reduce之前,尽可能的让每个线程多加几个元素,比如shared_data大小为256,输入数组大小为2560,那么就让每个线程加10个元素,变为256个元素依次赋值到shared_data然后再做reduce,这样计算快的原因是充分利用了线程,如果一上来就做reduce,每次都有一半的线程会浪费掉,倒不如在此之前多加一些元素)

除了Scalar Reduction还有Column Reudction、Row Reduction等,具体可以参考tensorflow源码:https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/kernels/reduction_gpu_kernels.cu.h

其中在列数或者行数少于16时,还用到了warp-primitive层级的编程技巧,具体可参考:https://devblogs.nvidia.com/using-cuda-warp-level-primitives/

原因很简单:列数小于16时,一个warp能算最少两行或者两列,因此需要将每个warp内的几个数加和,正好可以利用warp-primitive特性计算这个和.

tensorflow在内部调用了cub库提供的API(cub好像就是包装了一些cuda API),其实完全可以自己实现.

原文地址:https://www.cnblogs.com/deepllz/p/11350764.html