用CPU计算的程序和用GPU计算的程序有什么异同?

想把一个程序改成并行计算,能介绍点入门知识不

推荐  (0) |
收藏 |
3人关注关注
2个答案
13 0

傅里叶变黄油猫软件工程师,应用数学专业

2013-10-15 18:22

GPU编程和CPU有很大的不同,我觉得最好的解释方法是代码:

我们要写一条程序在CPU上运行,以对两个数组执行对位相加,常规的方法是:
for(size_t k = 0 ; k < N ; ++k)
c[k] = a[k] + b[k];

如果要做同样一件事,GPU上的程序看起来是这样的:
__kernel void Add(__global int* a, __global int* b,__global int* c)
{
size_t k = get_global_id(0);
c[k] = a[k] + b[k];
}

以上是一条OpenCL规范的“内核”,它看起来很像一个函数,执行一次这个函数只计算一个单元的加。然后我们要将这段代码通过OpenCL框架编译,再由普通的CPU程序(称为主机程序)调用OpenCL接口在GPU上启动它。启动时指定数组的大小“N”,别的事情就完全交给GPU完成了。

====分割线====

我用上面的例子解释GPU是怎么工作的,从而说明GPU为什么擅长并行计算:

以上的例子里,GPU通过计算规模N启动内核,即把整个任务划分成N个子任务,每个子任务都是相同地执行一次内核函数,我们称这些子任务为“线程”,尽管他们与CPU的线程很不相同。而GPU怎样调度这些线程,你是无法控制的,它完全可以不按顺序执行。

实际上GPU是怎样调度的呢?用一个现代的GPU做例子,例如GeForce GTX Titan。Titan拥有14个“SM”,OpenCL里叫“计算单元”,类似一个CPU核,但不同于CPU核同时执行一个线程,SM可同时执行2048个线程而几乎没有线程间切换开销。于是GPU一开始就把14组每组2048个线程分配给所有SM。每个SM拥有192个可执行整数运算、单精度浮点运算的流水线,每个时钟周期最多会把192个线程的一条指令塞进流水线,用不了几个周期就能完全调度2048条加法指令,直到所有线程的计算结果都完成,SM就会再向GPU控制器取下一组2048个线程。以上介绍省略了很多细节,不过基本就是这么回事了。

归纳地说,GPU可同时调度大量相同的工作。由于所有子任务的指令完全一样,所以GPU并不需要每线程都用一套控制器,而是一个控制器同时调度大量线程,如此节省晶体管数、提高数据吞吐量。因此,要充分发挥GPU的性能,必须将任务分解成大量相同的子工作,少量而复杂的工作并不是GPU的强项。

====分割线====

在实际应用中,你要为完成一套完整的计算写多个内核,并由主机程序决定每个内核的执行顺序、计算规模、输入参数,最终将计算结果从GPU内存复制到系统内存并输出。

学习GPU编程需要对GPU的硬件特点有充分理解,从而学会如何优化代码,这也是一个很大的区别。优质的GPU代码必须能“喂饱”GPU的各种资源,让它们总是运行在最忙的状态,从而获得最佳的性能,而GPU比CPU难喂饱得多。例如“合并内存访问”是一个很重要的GPU特性,如果有些代码写得有问题,导致GPU无法合并访问,可导致性能下降90%以上。实际上GPU的架构远比上面介绍的复杂,而且不同厂商的GPU架构又不一样,所以性能优化是很复杂的工作,从算法层面到代码层面都要考虑,可以说GPU编程易学难精。

目前通用计算编程框架主要有OpenCL(全平台通用)、CUDA(NV卡在所有平台可用)、DirectCompute(所有厂商的设备在Windows平台下可用),基本上原理都一样,CUDA能更精确地控制NV卡所以能做最大程度的优化,根据自己的需要选一个吧。我选的是OpenCL,基本学习方法是OpenCL官方文档+搜索,1周左右已入门,对有基本英文能力和编程基础的人一点都不难。我最近就搞了个用OpenCL算圆周率的小软件:
http://www.guokr.com/blog/483329/

文档推荐OpenCL规范。之后看 NVidia OpenCL/CUDA最佳实践指南,介绍NV GPU是怎么工作的,大部分原理是AMD通用。

0 0

楼上已经说的清楚,我废话一句“并不是每个程序都可以并行运算”

查看更多

添加回答

登录 后回答问题,你也可以用以下帐号直接登录

相关问答

关于我们 加入果壳 媒体报道 帮助中心 果壳活动 免责声明 联系我们 移动版 移动应用

©2017果壳网    京ICP证100430号    京网文[2015] 0609-239号    新出发京零字东150005号     京公网安备11010502007133号

违法和不良信息举报邮箱:jubao@guokr.com    举报电话:13691127034