【CUDA开发】 CUDA Thrust 规约求和
1. 使用 Thrust
Thrust 是一个开源的 C++ 库,用于开发高性能并行应用程序,以 C++ 标准模板库为蓝本实现。
官方文档见这里:CUDA Thrust
/* ... */
float *fMatrix_Device; // 指向设备显存
int iMatrixSize = iRow * iCol; // 矩阵元素个数
cudaMalloc((void**)&fMatrix_Device, iMatrixSize * sizeof(float)); // 在显存中为矩阵开辟空间
cudaMemcpy(fMatrix_Device, fMatrix_Host, iMatrixSize * sizeof(float), cudaMemcpyHostToDevice); // 将数据拷贝到显存
thrust::device_ptr<float> dev_ptr(fMatrix_Device);
float thrustResult = thrust::reduce(dev_ptr, dev_ptr + size_t(iMatrixSize), (float)0, thrust::plus<float>());
其中,fMatrix_Host 为指向主机内存的矩阵的头指针。
2. 我的 Reduction
/**
* 每个 warp 自动同步,不用 __syncthreads();
* volatile : 加上关键字volatile的变量将被定义为敏感变量,意思是加了volatile
* 的变量在内存中的值可能会随时发生变化,当程序要去读取这个变量时,
必须要从内存中读取,而不是从缓存中读取
* sdata 数组头指针,数组位于共享内存
* tid 线程索引
*/
__device__ void warpReduce(volatile float *sdata, int tid)
{
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];
}
/**
* 优化:解决了 reduce3 中存在的多余同步操作(每个warp默认自动同步)。
* globalInputData 输入数据,位于全局内存
* globalOutputData 输出数据,位于全局内存
*/
__global__ void reduce4(float *globalInputData, float *globalOutputData, unsigned int n)
{
__shared__ float sdata[BLOCK_SIZE];
// 坐标索引
unsigned int tid = threadIdx.x;
unsigned int index = blockIdx.x*(blockDim.x * 2) + threadIdx.x;
unsigned int indexWithOffset = index + blockDim.x;
if (index >= n) sdata[tid] = 0;
else if (indexWithOffset >= n) sdata[tid] = globalInputData[index];
else sdata[tid] = globalInputData[index] + globalInputData[indexWithOffset];
__syncthreads();
// 在共享内存中对每一个块进行规约计算
for (unsigned int s = blockDim.x / 2; s>32; s >>= 1)
{
if (tid < s) sdata[tid] += sdata[tid + s];
__syncthreads();
}
if (tid < 32) warpReduce(sdata, tid);
// 把计算结果从共享内存写回全局内存
if (tid == 0) globalOutputData[blockIdx.x] = sdata[0];
}
/**
* 计算 reduce4 函数的时间
* fMatrix_Host 矩阵头指针
* iRow 矩阵行数
* iCol 矩阵列数
* @return 和
*/
float RuntimeOfReduce4(float *fMatrix_Host, const int iRow, const int iCol)
{
float *fReuslt = (float*)malloc(sizeof(float));;
float *fMatrix_Device; // 指向设备显存
int iMatrixSize = iRow * iCol; // 矩阵元素个数
cudaMalloc((void**)&fMatrix_Device, iMatrixSize * sizeof(float)); // 在显存中为矩阵开辟空间
cudaMemcpy(fMatrix_Device, fMatrix_Host, iMatrixSize * sizeof(float), cudaMemcpyHostToDevice); // 将数据拷贝到显存
/* ... */
for (int i = 1, int iNum = iMatrixSize; i < iMatrixSize; i = 2 * i * BLOCK_SIZE)
{
int iBlockNum = (iNum + (2 * BLOCK_SIZE) - 1) / (2 * BLOCK_SIZE);
reduce4<<<iBlockNum, BLOCK_SIZE>>>(fMatrix_Device, fMatrix_Device, iNum);
iNum = iBlockNum;
}
cudaMemcpy(fReuslt, fMatrix_Device, sizeof(float), cudaMemcpyDeviceToHost); // 将数据拷贝到内存
/* ... */
cudaFree(fMatrix_Device);// 释放显存空间
return fReuslt[0];
}
上述程序是优化的最终版本,优化的主要内容包括:
1. 避免每个 Warp 中出现分支导致效率低下。
2. 减少取余操作。
3. 减小不必要的同步操作,每个warp都是默认同步的,不用额外的同步操作。
4. 减小线程的闲置,提高并行度
3. 时间对比
数据的大小为:
iRow = 1000;
iCol = 1000;
时间为:
ReduceThrust 的运行时间为:0.179968ms.
494497
Reduce0 的运行时间为:0.229152ms.
494497
Reduce1 的运行时间为:0.134816ms.
494497
Reduce2 的运行时间为:0.117504ms.
494497
Reduce3 的运行时间为:0.086016ms.
494497
Reduce4 的运行时间为:0.07424ms.
494497
CPU的运行时间为:1 ms.
494497
数据的大小为:
iRow = 2000;
iCol = 2000;
时间为:
ReduceThrust 的运行时间为:0.282944ms.
1.97828e+006
Reduce0 的运行时间为:0.779776ms.
1.97828e+006
Reduce1 的运行时间为:0.42624ms.
1.97828e+006
Reduce2 的运行时间为:0.343744ms.
1.97828e+006
Reduce3 的运行时间为:0.217248ms.
1.97828e+006
Reduce4 的运行时间为:0.160416ms.
1.97828e+006
CPU的运行时间为:3 ms.
1.97828e+006
数据的大小为:
iRow = 4000;
iCol = 4000;
时间为:
ReduceThrust 的运行时间为:0.536832ms.
7.91319e+006
Reduce0 的运行时间为:2.9919ms.
7.91319e+006
Reduce1 的运行时间为:1.56054ms.
7.91319e+006
Reduce2 的运行时间为:1.26618ms.
7.91319e+006
Reduce3 的运行时间为:0.726016ms.
7.91319e+006
Reduce4 的运行时间为:0.531712ms.
7.91319e+006
CPU的运行时间为:11 ms.
7.91319e+006
数据的大小为:
iRow = 6000;
iCol = 6000;
时间为:
ReduceThrust 的运行时间为:0.988992ms.
1.7807e+007
Reduce4 的运行时间为:1.09286ms.
1.7807e+007
CPU的运行时间为:25 ms.
1.7807e+007
数据的大小为:
iRow = 11000;
iCol = 11000;
时间为:
ReduceThrust 的运行时间为:2.9208ms.
5.98583e+007
Reduce4 的运行时间为:3.36998ms.
5.98583e+007
CPU的运行时间为:85 ms.
5.98583e+007
从上可以看出,2 中介绍的几种优化方式取得了良好的效果;另外,当数据量较少时,我自己优化的规约函数比 Thrust 中的规约更高效,但是当数据量大于 4000 * 4000 时,Thrust 更高效,因此还有优化的空间。
4. 完整代码
【CUDA开发】 CUDA Thrust 规约求和的更多相关文章
- CUDA开发 - CUDA 版本
"CUDA runtime is insufficient with CUDA driver"CUDA 9.2: 396.xx CUDA 9.1: 387.xx CUDA 9.0: ...
- 【CUDA开发】Thrust库
Thrust库从C++的STL中得到灵感,将最简单的类似于STL的结构放在Thrust库中,比如STL中的vector.此外,Thrust库还包含STL中的算法和迭代器. Thrust函 ...
- Windows平台CUDA开发之前的准备工作
CUDA是NVIDIA的GPU开发工具,眼下在大规模并行计算领域有着广泛应用. windows平台上面的CUDA开发之前.最好去NVIDIA官网查看说明,然后下载对应的driver. ToolKits ...
- 【ARM-Linux开发】【CUDA开发】【深度学习与神经网络】Jetson Tx2安装相关之三
JetPack(Jetson SDK)是一个按需的一体化软件包,捆绑了NVIDIA®Jetson嵌入式平台的开发人员软件.JetPack 3.0包括对Jetson TX2 , Jetson TX1和J ...
- 【CUDA开发】CUDA面内存拷贝用法总结
[CUDA开发]CUDA面内存拷贝用法总结 标签(空格分隔): [CUDA开发] 主要是在调试CUDA硬解码并用D3D9或者D3D11显示的时候遇到了一些代码,如下所示: CUdeviceptr g_ ...
- 【CUDA开发】CUDA编程接口(一)------一十八般武器
子曰:工欲善其事,必先利其器.我们要把显卡作为通用并行处理器来做并行算法处理,就得知道CUDA给我提供了什么样的接口,就得了解CUDA作为通用高性能计算平台上的一十八般武器.(如果你想自己开发驱动,自 ...
- 【神经网络与深度学习】【CUDA开发】caffe-windows win32下的编译尝试
[神经网络与深度学习][CUDA开发]caffe-windows win32下的编译尝试 标签:[神经网络与深度学习] [CUDA开发] 主要是在开发Qt的应用程序时,需要的是有一个使用的库文件也只是 ...
- 【神经网络与深度学习】【CUDA开发】【VS开发】Caffe+VS2013+CUDA7.5+cuDNN配置过程说明
[神经网络与深度学习][CUDA开发][VS开发]Caffe+VS2013+CUDA7.5+cuDNN配置过程说明 标签:[Qt开发] 说明:这个工具在Windows上的配置真的是让我纠结万分,大部分 ...
- 【视频开发】【CUDA开发】ffmpeg Nvidia硬件加速总结
原文链接:https://developer.nvidia.com/ffmpeg GPU-accelerated video processing integrated into the most p ...
随机推荐
- PHP swoole UDP服务端和客户端
服务端 <?php $serv = ,SWOOLE_PROCESS,SWOOLE_SOCK_UDP); $serv->on('Packet',function ($serv,$data,$ ...
- 问题[scrapy.spidermiddlewares.offsite] DEBUG: Filtered offsite request to...
原因是二次解析的域名被过滤掉了, 解决办法 解决办法一: yield scrapy.Request(url=detail_url, meta={'item': item}, callback=self ...
- Codeforces Round #446 Div1 E
题目大意 有n个数,进行k轮操作:随机一个i,让\(a_i\)减1,然后ans加上\(\Pi_{j\neq i}a_i\). 求ans的期望. 分析 发现,造成的伤害就是原来的ai的积减去k轮操作后的 ...
- ueditor编辑器+粘贴word
最近公司做项目需要实现一个功能,在网页富文本编辑器中实现粘贴Word图文的功能. 我们在网站中使用的Web编辑器比较多,都是根据用户需求来选择的.目前还没有固定哪一个编辑器 有时候用的是UEditor ...
- virtualbox使用xshell配置以及共享文件夹设置
1.virtualbox NAT网络配置后,host xshell访问 设置映射 登陆: ssh 127.0.0.1 2.virtualbox共享文件(host---->guest) 1.安装增 ...
- TensorFlow使用记录 (七): BN 层及 Dropout 层的使用
参考:tensorflow中的batch_norm以及tf.control_dependencies和tf.GraphKeys.UPDATE_OPS的探究 1. Batch Normalization ...
- AcWing:109. 天才ACM(倍增 + 归并排序)
给定一个整数 MM,对于任意一个整数集合 SS,定义“校验值”如下: 从集合 SS 中取出 MM 对数(即 2∗M2∗M 个数,不能重复使用集合中的数,如果 SS 中的整数不够 MM 对,则取到不能取 ...
- puppet自动化部署
puppet自动化部署 puppet 实现运维自动化管理的软件. 官方网站: http://puppetlabs.com/ pupptet下载链接:http://downloads.puppe ...
- C++入门经典-例7.10-运算符的重载,重载加号运算符
1:曾经介绍过string类型的数据,它是C++标准模版库提供的一个类.string类支持使用加号“+”连接两个string对象.但是使用两个string对象相减确实非法的,其中的原理就是C++所提供 ...
- LeetCode 216. 组合总和 III(Combination Sum III)
题目描述 找出所有相加之和为 n 的 k 个数的组合.组合中只允许含有 1 - 9 的正整数,并且每种组合中不存在重复的数字. 说明: 所有数字都是正整数. 解集不能包含重复的组合. 示例 1: 输入 ...