CUDA杂谈
这一年都在编写CUDA的程序,用了很多优化的手段,发现大部分其实还是官方的指南里面的手段
https://docs.nvidia.com/cuda/cuda-c-best-practices-guide/
https://developer.download.nvidia.cn/compute/cuda/1.1-Beta/x86_website/projects/reduction/doc/reduction.pdf
至于代码,多看CUDA自带的example就好了,挺好的代码
学会使用trust库
后面才发现有这个库的,具体效率没看过,但是发现很多我手写的代码trust里面都有,下次可以用用。
内存方面
CUDA里面,用nsight一看,有大部分时间都花在cudaMalloc,cudaMemcpy这一类的函数里面,所以如何减少这些函数调用是很重要的
减少cudaMalloc,cudaMemcpy的调用
cudaMalloc是很耗时的一个操作,我在优化雷达数据计算的时候,一份数据用CPU算要80ms,但是用GPU算只要10,如果用GTX1080ti的话也才6ms左右,但是单单cudaMalloc就用了10几ms.特别在多线程下,这个问题特别严重
所以不要轻易回收申请的GPU内存,能复用就复用,能实现一个简单的内存池最好
多线程同时操作内存
void func()
{
char *p = nullptr;
cudaMalloc((void**)&p, 1024 * 1024 * 10);
cudaFree(p);
}
int main()
{
std::thread t(func);
std::thread t2(func);
std::thread t3(func);
t.join();
t2.join();
t3.join();
}
上面的代码同时开启3个线程,申请了三块显存, 可以看到,每个malloc的申请都在100ms之间.我估计应该是产生竞争了
后来写代码发现,是每个线程在第一次执行CUDA的代码的时候,会比较慢。修改了代码,在代码前面加入create stream,发现createstream比较慢,而cudaMalloc快了点,但是依然有4-10ms的消耗,所以我估计还是有一定的竞争
而每个线程第一次调用CUDA函数会很慢是因为CUDA的每个线程需要初始化一些东西吧,找了版本也没找到相关的说明,有人说是context,但是从nsight里面看到,大部分的context都是一样的

将代码修改成串行申请内存,可以看到内存申请只有第一个比较耗时,第二个第三个都是很快的
void func()
{
char *p = nullptr;
cudaMalloc((void**)&p, 1024 * 1024 * 10);
cudaFree(p);
}
int main()
{
func();
func();
func();
}

拷贝内存
static const int malloc_size = 1024 * 1024 * 10;
void func()
{
cudaStream_t stream;
cudaStreamCreate(&stream);
char *gpu_mem = nullptr;
char *host_mem = (char*)malloc(malloc_size);
cudaMalloc((void**)&gpu_mem, malloc_size);
cudaMemcpy(gpu_mem, host_mem, malloc_size, cudaMemcpyHostToDevice);
cudaMemcpy(host_mem, gpu_mem, malloc_size, cudaMemcpyDeviceToHost);
cudaFree(gpu_mem);
free(host_mem);
}
开多线程拷贝

单线程拷贝内存

可以看到单线程的内存拷贝比较稳定,而多线程在2-10ms之间,不知道是不是因为多线程操作内存引起的部分等待
网上说 可以使用stream进行异步传输,于是修改代码,使用async的memcpy
cudaStream_t stream;
cudaStreamCreate(&stream);
char *gpu_mem = nullptr;
char *host_mem = (char*)malloc(malloc_size);
cudaMalloc((void**)&gpu_mem, malloc_size);
cudaMemcpyAsync(gpu_mem, host_mem, malloc_size, cudaMemcpyHostToDevice,stream);
cudaMemcpyAsync(host_mem, gpu_mem, malloc_size, cudaMemcpyDeviceToHost,stream);
cudaFree(gpu_mem);
free(host_mem);
最终结果,表示没啥鸟用,速度慢还是慢,从几张图的开始时间和结束时间来看,也没有看出什么异步的优势

pinned 内存
申请pinned内存耗时

拷贝pinned内存与拷贝非pinned内存对比

从上面图中可以看出,拷贝pinn内存基本是拷贝非pinn内存速度的7-9倍左右,效率提升还是很可观的
zero copy, shared memory
zero copy对我来讲几乎没什么用的东西,太过频繁在CPU和GPU写和读内存反而导致速度下降得很严重,最终被放弃了
shared memory对我来讲用处并不大,而且要修改太多的代码。我们代码里面主要时间还是花在GPU和CPU的交互,即使修改成使用shared memory最终估计也就优化几ms,没必要那么折腾
IO优化
IO优化主要是在三方面,知乎上的答案讲得很清楚了
gpu的io问题一直是比较严重的瓶颈,我自己总结有三种解决方案。
1.优化算法,选择更有效的存储方式,减少显存的使用。只拷贝必要数据,优化数据结构等等。
2.使用cuda内存优化技巧。比如显存整块申请和拷贝,使用pinned memory,shared memory,constant memory,使用流来掩盖内存延迟等等。
3.硬件解决方案,放弃pci-e,使用ibm的power架构和p100,直接用nv-link进行内存传输。这个方案是一劳永逸的,但是要准备好money,一整套下来很贵的。第三个方案一般整不起,前两个方案是算法和语言技巧方面,与算法本身有很大的关系。个人经验上来讲方案1提升的潜力比较大。
作者:杨伟光
链接:https://www.zhihu.com/question/52472621/answer/130949946
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
https://www.cnblogs.com/1024incn/p/5891051.html
最重要的
- 学会使用nvprof工具,优化这个才是关键
- 了解自己的程序是否适合做并行化,不了解自己的程序是否适合并行化的话,多读几本多线程相关的书籍,或者CPU内存操作优化的书籍,其实两者的优化思路都差不多.
- 注意一点,如果不熟悉CUDA的话,特别是那种执行本来只需要几百毫秒的算法,一部小心写出来的代码可能比CPU版本还慢,我们的雷达处理器就是一个很好的例子。最早要优化运算,CPU版本是200ms,我同事写出来的CUDA代码居然要300ms,后来经过我的优化,最后是60ms,主要是内存操作的优化
CUDA杂谈的更多相关文章
- CUDA[2] Hello,World
Section 0:Hello,World 这次我们亲自尝试一下如何用粗(CU)大(DA)写程序 CUDA最新版本是7.5,然而即使是最新版本也不兼容VS2015 ...推荐使用VS2012 进入VS ...
- CUDA[1] Introductory
Section 0 :Induction of CUDA CUDA是啥?CUDA®: A General-Purpose Parallel Computing Platform and Program ...
- Couldn't open CUDA library cublas64_80.dll etc. tensorflow-gpu on windows
I c:\tf_jenkins\home\workspace\release-win\device\gpu\os\windows\tensorflow\stream_executor\dso_load ...
- ubuntu 16.04 + N驱动安装 +CUDA+Qt5 + opencv
Nvidia driver installation(after download XX.run installation file) 1. ctrl+Alt+F1 //go to virtual ...
- 手把手教你搭建深度学习平台——避坑安装theano+CUDA
python有多混乱我就不多说了.这个混论不仅是指整个python市场混乱,更混乱的还有python的各种附加依赖包.为了一劳永逸解决python的各种依赖包对深度学习造成的影响,本文中采用pytho ...
- [CUDA] CUDA to DL
又是一枚祖国的骚年,阅览做做笔记:http://www.cnblogs.com/neopenx/p/4643705.html 这里只是一些基础知识.帮助理解DL tool的实现. “这也是深度学习带来 ...
- 【转】PHP 杂谈《重构-改善既有代码的设计》之一 重新组织你的函数
原文地址: PHP 杂谈<重构-改善既有代码的设计>之一 重新组织你的函数 思维导图 点击下图,可以看大图. 介绍 我把我比较喜欢的和比较关注的地方写下来和大家分享.上次我写 ...
- 基于Ubuntu14.04系统的nvidia tesla K40驱动和cuda 7.5安装笔记
基于Ubuntu14.04系统的nvidia tesla K40驱动和cuda 7.5安装笔记 飞翔的蜘蛛人 注1:本人新手,文章中不准确的地方,欢迎批评指正 注2:知识储备应达到Linux入门级水平 ...
- CUDA程序设计(一)
为什么需要GPU 几年前我启动并主导了一个项目,当时还在谷歌,这个项目叫谷歌大脑.该项目利用谷歌的计算基础设施来构建神经网络. 规模大概比之前的神经网络扩大了一百倍,我们的方法是用约一千台电脑.这确实 ...
随机推荐
- SSH不允许Root登陆的方法
不允许Root登陆的方法如下: vim /etc/ssh/sshd_config 把PermitRootLogin yes 改成: PermitRootLogin no 然后重启sshd服务: Ser ...
- 【转】 Pro Android学习笔记(五四):调试和分析(2):View层次结构
目录(?)[-] 帮助性能分析 帮助精简UI设计 对于模拟器上的应用(非真实设备),可以查看Hierarchy View,如下图: 帮助性能分析 当我们选择某个view时,我们可以看到measurin ...
- 【转】 Pro Android学习笔记(三七):Fragment(2):基础小例子
目录(?)[-] 小例子运行效果 Pre-step一点准备 Step 1Activity的布局 小例子运行效果 这是一个书名和书简介的例子.运行如下图.Activity由左右两个Fragment组成, ...
- java代码简单练习
总结: package com.ds; import java.awt.Color; import java.awt.FlowLayout; import javax.swing.JFrame; im ...
- css关于内外边距的详细解释
贴图吧,图一眼明了. 无效果时候有 只有一个<div>啦啦啦</div> 只有padding时候有: padding详细设计时: 解释:padding是对内的,如padding ...
- 人物-IT-张志东:张志东
ylbtech-人物-IT-张志东:张志东 张志东,广东东莞人,腾讯创办人之一,腾讯高级副总裁兼科技总裁,于1993年取得深圳大学理学学士学位,并于1996年取得华南理工大学计算机应用及系统架构硕士学 ...
- k8s 基础 核心概念
Pod pod是若干相关容器的集合,Pod包含的容器运行在同一台宿主机上,这些容器使用相同的网络命名空间,ip地址和端口,相互之间能通过localhost来发现和通信.另外,这些容器还可共享一块存储空 ...
- tomcat jsp 数字串传值异常问题
1.在下面的jsp内嵌java代码去除num之前,有某Controller已经有了操作: request.getSession().setAttribute("num", ...
- 阿里巴巴Druid数据库连接池的使用
准备: 创建一个基于SpringBoot的web项目 1 引入相关依赖 jpa.mysql.druid <?xml version="1.0" encoding=" ...
- Angular11 模板表单、响应式表单(自定义验证器)、HTTP、表单元素双向绑定
1 模板表单 模型通过指令隐式创建 技巧01:需要在模块级别引入 FormsModule ,通常在共享模块中引入再导出,然后在需要用到 FormsModule 的模块中导入共享模块就可以啦 impor ...