CUDA算子:reduce优化

如何对GPU中的reduce算法进行优化。官方地址

https://developer.download.nvidia.cn/assets/cuda/files/reduction.pdf

reduce算法的本质:x = x_{0}\bigotimes x_{1}\bigotimes x_{2}...\bigotimes x_{n-1}\bigotimes x_{n}

并行算法设计

GPU中,reduce采用了树形的计算方式

从上到下,将数据不断累加,直到得出最后的结果,25。GPU没有针对global数据的同步操作,只能针对block的数据进行同步。所以将reduce分为两个阶段,示意图如下:

 假设给定一个长度为N的数组,需要计算该数组的所有元素之和。首先需要将数组分为m个小份。在第一阶段,开启m个block计算出m个小份的reduce值。在第二阶段,使用一个block将m个小份再次进行reduce,得到最终结果。由于第二段本质上可以调用第一阶段的kernel,所以本文只探索第一阶段的优化技巧。

kernel接口

__global__void reduce(T *input, T* output)

input:输入的数组,一个长度为N的数组;output:输出的数组,第一阶段的结果,长度为M的数组。

在开始CUDA编程前,设置三个参数:

1.BlockNum开启的block数量,即M,代表需要将数组切成几份

2.Thread_per_block:每个block中开启的线程束,一般:128,256,512,1024

3.Num_per_block:每个block需要进行reduce操作的长度

其中:BlockNum*Num_per_block = N


reduce baseline算法:if (tid%(2*s)==0)

三个步骤:

1.将数据load至shared memory中

2.在shared memory中对数据进行reduce操作

3.将最后的结果写回global memory中。

在第一个步骤中,让Num_per_block和Thread_per_block一致,每个block设置256个线程,一个block负责256个数据的reduce工作。

假设需要处理32M(2^{5}*2^{20})的数据,则有128K(2^{7}*2^{10})个block。

tid:线程号;i:原始数组中的索引号。第tid号线程将第i号的数据从global中取出,放到shared memory的第tid元素中。比如在第0号block中,0号线程将0号元素取出,放到shared memory的第0号位置。

从硬件角度分析,为了执行代码,GPU需要分配存储资源计算资源。存储资源包括在global memory中分配的一块32M*sizeof(float)的空间以及在shared memory中分配的256*sizeof(float)的空间。shared

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值