《GPU高性能编程cuda实战》读书笔记


第一章:为什么需要cuda

GPU能实现很强的并行计算,cudac是对c进行了一定的扩展,学习cudac只需要c语言的基础即可,不需要opengl或者DX的知识。当然书中这里的意思其实是指,如果只是用GPU来计算的话,是不需要图形学和openglDX的知识的,但是如果你要做图形图像的应用,当然需要具备这些知识,比如后来提到的cudaopengl或者DX的互操作。


第二章:入门

这一章主要是简要介绍cuda开发环境的搭建。其实书中不够详细,看了书是不知道具体怎么操作的。所以我是看了官网和一些人的博客来为自己机器搭建了开发环境的。自己还总结了一下http://blog.csdn.net/linger2012liu/article/details/20907607



第三章:cudac简介

学习了第一个helloworldcuda程序。知道了原来一个cuda程序中,有cpu执行的代码,也有设备执行的代码,即在GPU执行。我们通过在cpu代码中调用核函数,让GPU代码执行。

还有一个小程序,学会了如何查询GPU的一些属性,比如GPU的计算能力。


第四章:cudac并行编程

第一个程序:这个例子是计算两个向量的相加,启用多个线程块来实现并行计算。

第二程序:一个Julia集的图像显示,了解了二维的线程格来表示多个线程块,其中julia计算没关注,还有图像的显示是调用了封装好了的类,也不关注。


第五章:线程协作

通过这章,才完全了解cuda的线程模型,有些概念,比如线程格,线程块,线程,这些还分为一维和二维的,要学会怎么获取当前函数执行所在的线程,线程块。自己也总结了一下http://blog.csdn.net/linger2012liu/article/details/20933647

共享内存:通过__shared__关键字来申请。共享内存缓冲区驻留在物理GPU上,访问速度高于普通缓冲区。所谓的共享内存,是指同一线程块中,里面线程共享。 线程同步也是。块与块之间不影响。(p64

因为共享内存会引发竟态现象,这里介绍了通过线程同步(syncthreads)的方法来避免。当某些线程需要执行一条指令,而其他线程不需要执行时,这种情况就成为线程发散。cuda架构规定,除非线程块中的每个线程都执行了syncthreads(),否则没有任何线程能执行syncthreads之后的指令。

这里还学会了一个小技巧,就是当计算的任务数量超过了总的线程数量的限制的时候,得把任务分解,按线程数量来分,相当于让一个线程串行计算几个任务。


第六章:常量内存与事件

知道了使用常量内存可以提高性能,

对常量内存的单次读操作可以广播到其他的邻近线程(线程束),

常量内存的数据将缓存起来,对相同地址的连续读操作不会产生额外的内存通信量。

GPU常量声明:

_constant_Sphere s[SPHERES];

常量初始化:从CPU拷贝到GPUcudaMemcpyToSymbol

线程束,常量,缓存,内存



这章还提到使用事件来计算时间来测量性能。

cudaEventSynchronize等待GPU事件完成

cudaEventDestroy

其实对这个同步函数不是很理解,代码的使用是这样的

//get stop time, and display the timing results

HANDLE_ERROR(cudaEventRecord( stop, 0 ) );

HANDLE_ERROR(cudaEventSynchronize( stop ) );

为啥cudaEventSynchronizecudaEventRecord之后,而不是之前呢。


第七章:纹理内存

一维纹理和二维纹理内存

纹理内存是只读内存

纹理内存适用场景:内存访问存在大量空间局部性,一个线程读取的位置可能与邻近线程读取的位置非常接近


第八章:图形互操作性

之前的章节图像的显示都是用到了封装的一个类,叫CPUBitmap,该类的实现是把图像数据通过CPU调用驱动程序。本章主要是直接让GPU调用驱动程序,直接显示图像。这一章节要懂一点opengl的知识才能看懂。由于自己也是关注并行计算,而不是图像显示,先不用深入。

共享数据缓冲区是cuda核函数和opengl渲染操作之间实现互操作的关键部分。

要在执行绘制任务之前取消映射,这是为了确保应用程序的cuda部分和图形部分之间实现同步,使得在cudaGraphicsUnmapResourese之前的所有cuda操作完成之后,才会开始执行图形调用。


第九章:原子性

高并发总是会涉及到一些原子性的操作的问题。书中的有一个反面例子,当大量线程同时要操作同一块内存时,使用了原子操作,结果导致这些操作串行化,计算效率反而降低了。由于这个例子用到的是全局的内存,所以所有线程块的所有线程都会参与竞争。书中的优化发方法是,通过加入共享内存来减少竞争。例子不错,是关于字符直方图统计的。



第十章:流

cuda流表示一个GPU操作队列,并且该队列中的操作将以指定的顺序执行。

宽度优先使用流

支持设备重叠功能的GPU能够在执行一个CUDAC核函数的同时,还能在设备与主机之间

执行复制操作。可以使用多个流来实现这种计算与数据传输的重叠。

硬件在处理内存复制和核函数执行时分别采用不同的引擎:内存复制引擎和核函数执行引擎

我们之所以可以提高效率,是因为存在这么一种情况:stream0在执行内存复制的时候,stream1可以执行计算。内存复制引擎和核函数执行引擎可以同时运作,但是同一流的操作是串行的。


第十一章:多GPUcudac

零拷贝内存:通过cudaHostAllocMapped标志分配,是固定内存,cudac核函数可以直接访问这种主机内存。

对于集成GPU,使用零拷贝内存通常都会带来性能提升,因为内存在物理上与主机是共享的。

如果输入内存和输出内存都只能使用一次时,那么在独立GPU上使用零拷贝内存将带来性能提升。


每个GPU需要有一个不同的CPU线程来控制。

因此多GPU的编程,其实就是起不同的cpu线程控制不同的GPU

每个线程函数跟单个GPU的编程是一样的。


固定内存只是对于分配他们的线程是页锁定的,

如果线程共享了这块内存,那么其他线程将把这块内存视为标准可分页的内存。

可移动固定内存:线程之间可以移动,每个线程视其为固定内存。



第十二章:后记

介绍了一些cuda工具库,学习资源,挺有用的。


你可能感兴趣的:(cuda(GPU,programming))