Udacity cs344Unit 1-Introduction to Parallel Programming笔记(超详细,CUDA,并行,GPU

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

这两位有答案

猜你喜欢

转载自blog.csdn.net/Ria_Ria/article/details/80558815
今日推荐