0.课程简介:要学并行思维,是最重要的,当在别的领域遇到瓶颈时,并行思维也许能帮上忙
课程链接:点我
Unit 1
1.举例,怎么能更快的从美国挖洞到中国
解决方案
a.用一个铲子,从每2秒挖一下,变成每1秒挖一下,有上限,太快铲子会断
(提高处理器的时钟频率,会增加能耗,每个芯片能耗都有上限)
b.用有两个铲子头的铲子,但是有工艺的限制,不能有100个铲子头
(每个时钟周期进行更多的工作)
c.雇佣更多的人,也有问题:怎么管理?会不会互相妨碍,怎么保证是朝深挖而不是朝宽
(并行计算,不只是雇佣有一个铁铲的人,而是雇佣有多个铁铲的人)
2.
3.从技术趋势讲起:为啥并行在整个世界如此风靡?
好消息:现代处理器是由晶体管构成的,这些晶体管体积在逐年变小,所以能在芯片上集成越来越多晶体管,所以有越来越多的计算资源可用。
坏消息:由于晶体管的改进,处理器设计者能够增加处理器的时钟频率,使他们每年运行的越来越快。但是现在已经到极限了是因为集成太多了之后,每个晶体管都会散发出热量,我们没有办法使其冷却下来以保证工作性能,所以我们要转变思路了,从过去我们使单个处理器变得越来越快(CPU是处理能力很厉害,相应的它的电能消耗也大,设计代价昂贵),我们想在固定用电量的情况下,计算效益最高——在GPU中制造大量的并行计算单元,每个计算单元就像小鸡,但是我们能把大量的计算单元放入到一块芯片中(就像耕地的面积大小有限,买两头牛的成本挺高的,而且这一片地只能放进去两头牛,所以不如买50只小鸡,效率不一定比牛差)。挑战是啥?怎么编程才能使得他们共同协作来解决复杂问题?
4.当我们制造一个高性能处理器时,当然是能耗最佳的,我们需要优化那些性能指标?
a.minimizing latency(缩短执行时间,以时间单位来衡量):执行时间指的是the amount time to complete a task
b.throughout(吞吐量,以单位时间完成的工作量来衡量):tasks completed per unit time
遗憾!这两个目标并不一定一致,CPU专注于缩短单个任务的执行时间,而GPU专注于提高吞吐量
可以看到,有时候随着吞吐量变小,延迟也在变小,但是GP设计师是优先考虑吞吐量的
5.考虑GPU设计师是怎做决定的
a.GPU有很多简单计算单位,在一起可以执行大量计算(愿意牺牲控制来换更多的计算能力)
b.GPU有一个显式并行编程模型(它就是有多个处理器,编程时候就要有认知)
c.GPU专著于改善吞吐量而不是延迟(愿意)
6.异构计算机
有两个不同的处理器:CPU和GPU
CUDA允许我们在一个程序中对两个处理器进行编程,所以我们可以使用GPU的力量了
给GPU编程基础也是C,不过扩展了一些我们用来表示并行的。CUDA编译器将编译你的程序,拆成两份,分别给CPU和GPU;假设的是CPU和GPU都有自己的内存(DRAM),CPU是主导,向GPU发送指示告诉它做什么
kernel:在GPU上调用,并以并行方式计算的程序
7.典型的程序过程
与计算相比,传输量很小这种,才适合用GPU算,不然合不上传一次。
8.编写kernel
你在编写kernel程序时候,看起来是编写的串行程序,但是当CPU调用时,就会配置到底要用多少个线程来执行kernel,这些线程每一个都会调用一遍kernel
9.GPU擅长什么
10.举例子:计算从1—63的平方
我们要将线程,看成是代码执行的一个独立路径
CPU中
一共执行64此乘法,假设每次两秒,一共128秒
GPU:分成了两部分,一部分运行在CPU上,一部分运行在GPU上
a.GPU part:只做一件事——表达 输出=输入*输入(看起来就像串行程序一样)
b.CPU part:分配内存(allocate memory)
copy data to/form GPU
launch kernel:这就是表达线程并行程度的地方
第一步:你在GPU上写了一个kernel函数,每次它只在一个线程上运行
第二步:你在CPU上launch many threads,每个都会独立的运行上一步的kernel
11.代码
我们只能在GPU的数据上调用kernel,不可能在CPU上
CPU data:h_...
GPU data: d_...
__global__是kernel函数的标志,
void意味着内核不会返回一个值
12.configuring the kernel launch(设置启动内核时候的参数):
Square<<<1,64>>>(d_out, d_in);
表面看起来是这样的
实际后台发生了啥呢?
when you launch a kernel ,你指定
<<<number of blocks,threads per block>>>(本例中,只有一个带有64个线程的块)
关于硬件你应该知道两件事
a.一次可以运行很多个块
b.每个块能装的线程数量有上限(新的GPU1024,旧的512)
事实上,当我们启动一个线程时候,它是知道它自己在block中的位置的(index),也知道在grid中的block位置(index)
有很多问题是2维(图像处理)或者3维的,CUDA支持多维
例如:处理128*128像素的图片
a.我们可以启动y维度上有128个block,每个block在x维度上有128个线程
b.启动8*8的block(x,y维度上各有8列),每个block里面是16*16的线程
所以CUDA支持1,2,3维的线程块
还有第三个参数
也就是说CUDA与生俱来就有很好的处理多维问题的能力
!!!!!!我们应该尽可能在问题中去找到更多的二维网格和块!!!!!!!
13.总结与扩展
拓展:我们刚刚学到的两个组成部分,将引导我们到一个有趣的抽象概念——映射
14.第一节课后的大练习:将一张彩色的图片转换成黑白的
https://github.com/ibebrett/CUDA-CS344/blob/master/Problem%20Sets/Problem%20Set%201/student_func.cu
https://blog.csdn.net/suda072605/article/details/17657203
这两位有答案