5年前将《GPU Gems 2》中的“Octree Textures on the GPU”用到了论文的实时纹理创作一节,那时候CUDA才刚出生,OpenCL应该还在规范阶段,所以将GPU用于加速和通用计算的成熟方法还是compution by texturing。至于同样的计算量在CPU和GPU上跑,性能到底提升多少,也没有做过对比实验。周末翻了下《CUDA by Example: An Introduction to General-Purpose GPU Programming》,基本掌握了用CUDA编写GPU思想和语法,比起将数据做为纹理、Shader写算法来,进步了不少:1)开发人员不需要熟悉渲染管线及图形API;2)不用花时间去搭建DX或者OpenGL的框架;3)Host与Device代码混编;4)不必采用Hacking思想处理包装成纹理的数据;5)可指定参与计算的线程数。有了如此方便的编程环境,就随手来做一下对比吧,这个例子来自《CUDA by Example》的4.2.2生成Julia集。
测试代码需要做一些调整,才能更好地体现出GPU的平行计算优势,这其中牵涉到支持CUDA的GPU架构知识,在这里做一下梳理。
在Nvidia推出Fermi架构之前,支持CUDA的Nvidia显示芯片都是由多个Streaming Multiprocessor(简称SM)组成,每个SM包含了八个Stream Processor(简称SP),每四个SP组成一个组,也就是说SM实际上可以看成包含两组4D的SIMD处理器。此外,每个SM还包含Register、share memory、texture cache以及constant cache。在执行 CUDA 程序的时候,每个SM对应一个 block,而每个SP就是对应一个 thread。虽然一个SM只有八个SP,但是由于SP进行各种运算都有延迟,更不用提内存存取的延迟了,因此 CUDA 在执行程序的时候,实际是以 warp 为单位。目前的支持CUDA显卡,一个 warp 里面有32个 threads,分成两组16 threads的half-warp。由于SP的运算至少有4个时钟周期的延迟,因此对一个4D的SP来说,一次至少执行16个 threads(即 half-warp)才能有效覆盖掉各种运算的延迟[1]。
图 1
在GeForce GTX 400系列上,Nvidia采用了全新的Fermi架构[2],之后的显卡的Compute Capability也从1.3跃升至2.0。SP改名为CUDA Core,提升到了32个/SM[3]。图2为Fermi核心演变,从GF104和由其发展起来的GF114、GF106、GF108的CUDA Core都上升到了48个/SM,支持2.1的Compute Capability,而GF100和GF110依旧是32个。最新基于Kepler架构的GeForce GTX 680支持3.0的Compute Capability,CUDA Core数量达到了192个/SM。
图 2
由于测试平台采用的是GTX 560 Ti,所以需要分析一下它的架构。GTX 560 Ti由8个SM组成,下图中,左边是从程序获取的设备属性,右边为单个SM内部结构示例图。可以看到,GTX 560 Ti的每个SM配备了两个Warp调度器,因此每个周期对两个包含32个线程的Warp进行分发。另外,对于一个二维图像,为kernel指定2D的grid和block可使代码更加直观。为此,block采用(16,16),总共分配256个(64*4)threads在一个SM上执行,如果需要产生1024*1024的Julia分形图,则需要grid为(64,64)。
图 3
测试平台为:
测试代码说明:
1)代码分为CPU实现和CUDA实现;
2)均采用CPU计时方法;
3)只针对计算部分测试,不包括内存分配、传输以及文件写入;
下面列出main函数代码,左边为CPU实现,右边为CUDA实现,均编译为release版本。
测试结论:CPU版本耗时244ms,CUDA版本耗时2.1087ms。这可是100倍的效率提升啊。不过CPU版本没有经过多核优化,所以这样这样对比实在不公平,但这却凸显出CUDA C将并行思想融入语言规则的优势。
在惊讶GPU用作通用计算的执行效率时,别忘了它还是有诸多应用上的问题:
1)初始化耗时,需要在显存分配空间,然后将数据从内存copy到显存;
2)数据量受GPU显存限制;
3)对本身就需要GPU参与运算的程序,如:3D游戏,通用计算会争夺GPU资源,如果做平衡?
4)计算数据之间的不相关性限制了GPU通用计算的应用范围;
5)CPU算法到适合GPU架构算法的移植;
最后,GPU硬件设计本身就已经决定了它的强项是密集数据处理(如:科学计算、医疗图像处理),在逻辑处理方面还是CPU的天下,所以它们是互补的,只会有整合而非替代的趋势。
[1] http://www2.kimicat.com/gpu%E7%9A%84%E7%A1%AC%E9%AB%94%E6%9E%B6%E6%A7%8B
[2] http://www.chip.cn/index.php?option=com_content&view=article&id=2857:geforce-gtx-400-gpu&catid=7:test-technology&Itemid=15
[3] http://www.geeks3d.com/20100606/gpu-computing-nvidia-cuda-compute-capability-comparative-table
[4] http://www.expreview.com/13590-2.html
[5] http://en.wikipedia.org/wiki/CUDA