CUDA C
一、CUDA结构
硬件:GPU(Graphics Processing Unit) SM(Streaming Multiprocessor) SP(Streaming Processor)
软件:Grid Blcok Thread
每个GPU由若干SM组成,每个SM由若干SP加上Register和shared memory组成,SP是真正执行线程的单元,这是GPU的硬件架构。
CUDA提供GBT逻辑结构,大致对应GSM
除此之外,GPU的调度单位是warp,基本上是32个Thread组成一个warp,由warp scheduler进行调度, 每个warp内的线程SIMT(Single Instruction Multi Thread)
二、CUDA基本语法
__global__ 声明一个kernel函数 , <<<block, thread>>> 调用kernel函数, block,thread可以是二维的(用dim3传入, dim3的结构为dim3(x, y, z))
—divece__ 声明一个函数,表示是在kernel中调用的
cudaMalloc(pointer, size);
cudaMemcpy(dest, src, size, direction)
cudaFree()
cudaDevicePro结构体
并形编程时offset的计算,一维二维不同
** 显存和主存的指针可以相互传递,但显存的读写只能在GPU上操作,内存的读写只能在CPU上操作,即设备上不能读写主存,CPU上不能读写设备内存 **
cudaSetDevice(i)有多个GPU时,选择一个i
cuda的好多函数都会返回一个cudaError_t类型的状态,如果是cudaSuccess,表示成功执行
注意:在执行了kernel函数后没有任何反应记得在kernel函数后添加cudaDeviceReset()指令,注意该指令必须要在kernel函数后,且在把设备内存中的内容复制到主存后。
三、cuda线程同步
__syncthreads()同步一个block内的线程,使block内的所有线程的__syncthreads()前面的代码全部运行完毕,才运行后面的代码,注意该同步指令不能放入分支结构中,否则会死锁永久等待。
注意:__syncthreads()只能同步一个block内的线程,无法同步block间的线程。
四、优化性能
__shared__ 声明shared memory, 每个block 共享shared memory,可读可写,芯片内部内存,相当于高速缓存。
__constant__ 声明constant memory,一般GPU会将显存分出64KB的constant memory,read-only,合理的使用constant memory有助于提高CUDA程序性能
注意:constant memory 只能静态分配,无需释放,其大小要在编译的时候确定, 并且要声明为全局。
原因:广播,half-warp thread 读同一个constant memory地址的时,只产生一次读操作 ,这样只占1/16的带宽(注意这个提升很大,因为GPU内部的处理单元很多,内存带宽已满足不了运算能力,the bottleneck is bandwidth)
cache,第一次读后,硬件会cache the constant data to GPU
duoble-edged sword:half-warp thread 都读一个constant memory,好剑,但若不同,则这16条thread读constant memory 将串行化,如果在global memory中即使不同也是并行的。
注意:用这个cudaMemcpyToSymbol(dist, src, size)拷贝constant memory
纹理内存,同常量内存有点像。
五、cuda事件
cudaEvent_t start, stop;
cudaEventCreate(&start); cudaEventCreate(&stop);
cudaEventRecord(start, 0); cudaEventRecord(stop, 0);
cudaEventSynchronize(stop);
float elapseTime;
cudaEventElapsedTime(&elapseTime, start, stop);
cudaEventDestroy(start); cudaEventDestroy(stop);
注意:cudaEvent is implemented directly on the GPU, it is not suitable to timing mixtures of divece and host code.
六、原子性
atomicAdd(&, value);
由于计算机中不满足浮点数加减法的结合率,故只提供了整数的atomicAdd()原子操作。但可以利用提供的对于整数的原子操作自己实现一个互斥锁,来实现临界资源的互斥访问。
struct Lock {
int *mutex;
Lock( void ) {
HANDLE_ERROR( cudaMalloc( (void**)&mutex,
sizeof(int) ) );
HANDLE_ERROR( cudaMemset( mutex, , sizeof(int) ) );
}
~Lock( void ) {
cudaFree( mutex );
}
__device__ void lock( void ) {
while( atomicCAS( mutex, , ) != );
__threadfence();
}
__device__ void unlock( void ) {
__threadfence();
atomicExch( mutex, );
}
};
【不确定】该互斥好像只能在块间有效执行,在块内线程之间就不行了。
七、流
前面的讨论的并行是相同任务不同数据的并行,流是不同任务间的并行(类似于CPU)
1、页锁定主机内存
cudaHostAlloc((void**)&add, ByteSize, cudaHostAllocDefault)分配固定内存,即不可分页,不可交换至磁盘(在释放之前),不可被其他程序占用
malloc(ByteSize)分配标准的可分页内存,可交换、可被占用
采用cudaHostAlloc分配的内存需要用cudaHostFree(add)释放,但还是可以用cudaMemcpy(),并且速度比用malloc()快
使用页锁定内存的一个好处:
- 加快主机内存和设备内存间的复制操作。由于设备内存和主机内存之间的交换用DMA来完成,不需要CPU的参与,故当使用可分页内存时,由于可能存在某页被换到磁盘中延缓DMA控制器的操作,故对于分页内存与设备内存交换时,系统先是申请了一块页锁定内存,先将内容拷贝进来,再将其与设备内存进行交换。即:可分页内存<->页锁定内存<->设备内存
2、流
创建流
cudaStream_t stream;
cudaStreamCreate(&stream);
流就好比一个任务对列,每个流中的任务串行执行,不同的流之间可以并行执行,但并不能全部并行,只能在内存拷贝和执行核函数上面并行
cudaMemcpyAsync(dest, src, size, direction, stream) 不同于cudaMemcpy和memcpy,后面两个是同步的,即函数执行完了,内存拷贝也就完成了,前者是一个异步方式,只是在流中提出了一个请求,并不一定完成了。
kernel<<<block, thread, 0, stream>>>()核函数也要指定相应的流变成异步执行,第三个暂时未知
所以最后需要一个同步机制来等待流中的任务完成cudaStreamSynchronize(stream)
最后释放流cudaStreamDestroy(stream)
使用页锁定内存的另一个好处:
- 异步
下面给个两个流的并行过程:
流1:HostToDevice kernel DeviceToHost
流2: HostToDevice kernel DeviceToHost
八、动态并行
前面讨论的并行是在主机函数调用kernel函数,但在kernel函数中能否继续调用kernel,cuda从某一版本开始后开始支持这一机制,称为动态并行。
九、注意点
- 在GPU中相邻线程访问相邻内存要比同一线程访问相邻内存的速度快。
参考:《cuda by exemple》
CUDA C的更多相关文章
- 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的实现. “这也是深度学习带来 ...
- 基于Ubuntu14.04系统的nvidia tesla K40驱动和cuda 7.5安装笔记
基于Ubuntu14.04系统的nvidia tesla K40驱动和cuda 7.5安装笔记 飞翔的蜘蛛人 注1:本人新手,文章中不准确的地方,欢迎批评指正 注2:知识储备应达到Linux入门级水平 ...
- CUDA程序设计(一)
为什么需要GPU 几年前我启动并主导了一个项目,当时还在谷歌,这个项目叫谷歌大脑.该项目利用谷歌的计算基础设施来构建神经网络. 规模大概比之前的神经网络扩大了一百倍,我们的方法是用约一千台电脑.这确实 ...
- 使用 CUDA范例精解通用GPU编程 配套程序的方法
用vs新建一个cuda的项目,然后将系统自动生成的那个.cu里头的内容,除了头文件引用外,全部替代成先有代码的内容. 然后程序就能跑了. 因为新建的是cuda的项目,所以所有的头文件和库的引用系统都会 ...
- CUDA代码移植
如果CUDA的代码移植,一个是要 include文件夹对不对,这个是.h文件能否找到的关键,另一个就是lib,这个是.lib文件能否找到的关键.具体检查地方,见下头. include: lib:
随机推荐
- Java数据类型(Primivite 和引用数据类型!)
一.byte(8位) short(16位) int(32位) long(64位) float(32位) double(64位) boolean(Java虚拟机决定) true 或者false! ...
- 深度学习原理与框架-图像补全(原理与代码) 1.tf.nn.moments(求平均值和标准差) 2.tf.control_dependencies(先执行内部操作) 3.tf.cond(判别执行前或后函数) 4.tf.nn.atrous_conv2d 5.tf.nn.conv2d_transpose(反卷积) 7.tf.train.get_checkpoint_state(判断sess是否存在
1. tf.nn.moments(x, axes=[0, 1, 2]) # 对前三个维度求平均值和标准差,结果为最后一个维度,即对每个feature_map求平均值和标准差 参数说明:x为输入的fe ...
- DLL 函数中使用结构体指针作函数参数(C# 调用 C++ 的 DLL)
存在的问题: 问题1:C++ 与 C# 同样定义的结构体在内存布局上有时并不一致: 问题2:C# 中引入了垃圾自动回收机制,其垃圾回收器可能会重新定位指针所指向的结构体变量. 解决方案: 问题1方案: ...
- 初探LaTeX
第一次使用LaTeX 步骤 1 安装LaTeX 通过官网http://www.tug.org/mactex/mactex-download.html下载Mac版LaTeX. 安装成功后会出现 步骤 ...
- python中的全局变量和局部变量
python中,对于变量作用域的规定有些不一样. 在诸如C/C++.java等编程语言中,默认在函数的内部是能够直接訪问在函数外定义的全局变量的,可是这一点在python中就会有问题.以下是一个样例. ...
- 剑指offer——栈的压入、弹出序列
题目:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个栈是否为该栈的弹出顺序.假设压入栈的所有数字都不相等.例如序列1,2,3,4,5是某个栈的压入顺序,序列4,5,3,2,1是该栈序列的一 ...
- runners
saltstack return 除了在配置文件中可以定义外(太繁琐),还可以自定义retunner,当然,这需要通过代码实现了,实现方式和自定义的pillar和grains类似,步骤如下: #创建_ ...
- 使用Dockerfile自定义一个包含centos,tomcat的镜像
1.首先建立一个专用的dockerfile目录,方便统一存放将要创建的Dockerfile文件及相关资源, 例如:mkdir mydockerself 2.定位到mydockerself路径下,下载l ...
- python 并发编程 锁 / 信号量 / 事件 / 队列(进程间通信(IPC)) /生产者消费者模式
(1)锁:进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的,而共享带来的是竞争,竞争带来的结果就是错乱,如何控制,就是加锁处理. 虽然使用加锁的形式实现了 ...
- Distance on the tree
Distance on the tree https://nanti.jisuanke.com/t/38229 DSM(Data Structure Master) once learned abou ...