霍光
近些年的计算领域,异构计算可算是最为引人注目的话题之一。过去几年里,以NVIDIA的CUDA为代表的基于C语言的API为GPU计算赢得了更广泛的用户。2009年,全球召开了两次异构计算大会。最近来自NVIDIA的消息中提到,目前CUDAZone网站上的CUDA应用程序与论文数量已经突破了500大关。
然而,异构计算还面临很多认识上的误区。例如,在一些报道里,提出了“未来GPU可能会取代CPU”、“GPU的内核数量是CPU的几百倍,计算速度与之成正比”等论调。
事实上,CPU与GPU从设计思路和架构上先天就存在着差异。这些差异决定了GPU不可能取代CPU,或者说,能取代CPU的GPU已经不再是GPU了。
异构计算的真正意义,其实在于发挥不同架构处理器在不同方面的优势,从而实现系统整体计算能力的最大化利用。
CPU和GPU从设计之初,其目标就各不相同,这可以用一个比喻来说明:电工专科的毕业生与英语专业的毕业生,前者修理电器的速度远远快于后者,这并不能说明前者的整体能力远高于后者——其实,对较复杂的进口电器,可能需要后者将说明书翻译成中文,前者再按照说明书将电器修好。
CPU在设计之初就是按照兼顾程序执行的并行性、通用性和平衡性的要求来规划的。在改进指令执行效率的过程中,CPU中被不停地加入新的指令集,这使得CPU已经成为计算机中设计最复杂的芯片。例如,除了支持常规指令集之外,英特尔的SSE、AMD的3DNow!等指令集都是在技术演进构成中逐渐加入CPU的,而仅SSE4指令集就包括54条新指令。
与之相反,GPU的单一处理核心却较诞生之初显得简单——最早,针对图形处理的关键计算,GPU将处理单元分为顶点着色器、光栅化引擎、纹理贴图单元等不同部分,分别完成不同计算任务。而统一渲染架构提出后,统一的计算单元取代了之前的不同单元。以NVIDIA GeForce 8800为例,它具有16组共128个统一标量着色器,也被称作流处理器。这里的每个流处理器实际上只能完成1D标量的加乘操作。在实际计算中,必须将所有的运算拆分成1D运算来执行。
从两者的差异可以看出,对于复杂指令调度、循环、分支、逻辑判断以及执行等的程序任务,GPU有心无力。只有在可拆分成简单指令的重复的高度并行数值计算中,GPU才能体现出其强大的能力。对此,美国Stone Ridge科技公司创始人兼总裁文森特(Vincent Natoli)曾做出“如果算法涉及许多分支指令,很难用流计算或SIMD处理,那么CPU将是最佳选择;如果算法是浮点SIMD类型的问题,可划分为许多对不同数据执行相同操作的独立线程,那么GPU将是很好的选择;如果问题主要涉及整数或定点,可以被转化为流的形式,具有非传统的数据表达形式和空间并行性,FPGA则是最佳选择”的论断。
另一方面,针对GPU的程序编写也较为困难。文森特指出,根据经验,即使使用CUDA这一很容易掌握的API,同一算法在CPU、GPU上开发的时间也大致为1∶1.25。
由以上分析可以看出,GPU与CPU并不存在取代的关系。相反,两者互相取长补短才能实现最终的良好系统表现。
为了更好地发挥不同架构处理器的能力,开发人员也在不遗余力地寻找更快捷地实现异构计算的方法。OpenCL就是建立异构计算标准的尝试之一。人们设计它的目的是“用平易近人的语言,使用不同的计算支援”。
如果OpenCL这个标准制定完成了,它将给异构计算带来多大的影响呢?让我们拭目以待。