开启新一片蓝海——异构计算完全解析
摘要:本文为您展现了近年来从并行计算到异构计算的发展历程,介绍了异构编程的开发标准:OpenCL、C++ AMP和Java Aparapi,引领读者步入异构计算的瑰丽殿堂,开启另一片蓝海。
导读:本文为您展现了近年来异构计算的发展历程,介绍了异构编程的开发标准:OpenCL、C++ AMP和Java Aparapi,引领读者步入异构计算的瑰丽殿堂。
并行计算:让处理的速度变得更快
相对于串行计算,并行计算可以划分成时间并行和空间并行。时间并行即流水线技术,空间并行使用多个处理器执行并发计算,当前研究的主要是空间的并行问题。以程序和算法设计人员的角度看,并行计算又可分为数据并行和任务并行。数据并行把大的任务化解成若干个相同的子任务,处理起来比任务并行简单。
空间上的并行导致两类并行机的产生,按照麦克·弗莱因(Michael Flynn)的说法分为单指令流多数据流(SIMD)和多指令流多数据流(MIMD),而常用的串行机也称为单指令流单数据流(SISD)。MIMD类的机器又可分为常见的五类:并行向量处理机(PVP)、对称多处理机(SMP)、大规模并行处理机(MPP)、工作站机群(COW)、分布式共享存储处理机(DSM)。
从自然哲学层面上来讲:任何最为复杂的事情,都可以被拆分成若干个小问题去解决。这就是当今并行计算的哲学理论依据。然而在当今的双路、四路、八路甚至多路处理器系统中,并行计算的概念早已得到广泛应用。目前业界最为普及的并行计算规范就是OpenMP。
OpenMP:同构计算最为普及的标准
OpenMP(Open Multi-Processing)是由OpenMP Architecture Review Board牵头提出的,并已被广泛接受的,用于共享内存并行系统的多线程程序设计的一套指导性注释(Compiler Directive)。OpenMP支持的编程语言包括C语言、C++和Fortran;而支持OpenMP的编译器包括Sun Studio和Intel Compiler,以及开放源码的GCC和Open64编译器。OpenMP提供了对并行算法的高层的抽象描述,程序员通过在源代码中加入专用的pragma来指明自己的意图,由此编译器可以自动将程序进行并行化,并在必要之处加入同步互斥以及通信。当选择忽略这些pragma,或者编译器不支持OpenMP时,程序又可退化为通常的程序(一般为串行),代码仍然可以正常运作,只是不能利用多线程来加速程序执行。
OpenMP的特色。OpenMP提供的这种对于并行描述的高层抽象降低了并行编程的难度和复杂度,这样程序员可以把更多的精力投入到并行算法本身,而非其具体实现细节。对基于数据分集的多线程程序设计,OpenMP是一个很好的选择。同时,使用OpenMP也提供了更强的灵活性,可以较容易的适应不同的并行系统配置。线程粒度和负载平衡等是传统多线程程序设计中的难题,但在OpenMP中,OpenMP库从程序员手中接管了部分这两方面的工作。
OpenMP的缺点。作为高层抽象,OpenMP并不适合需要复杂的线程间同步和互斥的场合。OpenMP的另一个缺点是不能在非共享内存系统(如计算机集群)上使用。由此如果我们想将不同类型的计算器、计算机联和起来,协同工作。我们就需要使用异构计算技术。
双剑岂可合璧:什么是异构计算?
异构计算(Heterogeneous computing)主要是指使用不同类型指令集和体系架构的计算单元组成系统的计算方式。常见的计算单元类别包括CPU、GPU等协处理器、DSP、ASIC、FPGA等。
异构计算近年来得到更多关注,主要是因为通过提升CPU时钟频率和内核数量而提高计算能力的传统方式遇到了散热和能耗瓶颈。而与此同时,GPU等专用计算单元虽然工作频率较低,具有更多的内核数和并行计算能力,总体性能-芯片面积比和性能-功耗比都很高,却远远没有得到充分利用。
广义上,不同计算平台的各个层次上都存在异构现象,除硬件层的指令集、互联方式、内存层次之外,软件层中应用二进制接口、API、语言特性底层实现等的不同,对于上层应用和服务而言,都是异构的。
从实现的角度来说,异构计算就是制定出一系列的软件与硬件的标准,让不同类型的计算设备能够共享计算的过程和结果。同时不断优化和加速计算的过程,使其具备更高的计算效能。
计算的发展历程:从32bit到异构计算
2003年以前,是32bit的时代。处理器制造厂商,不断提升制造工艺技术,使用更精细的制程来制造处理器。同时也不断提高处理器的时脉,如133MHz、166MHz、200MHz、300MHz……最终频率提升到了3GHz后,就难作寸进了。到目前为止我们也未曾见到Intel和AMD发布高于4GHz主频的处理器产品。
2003年出现了x86-64,有时会简称为“x64”,是64位微处理器架构及其相应指令集的一种,也是Intel x86架构的延伸产品。“x86-64”1999由AMD设计,AMD首次公开64位集以扩充给IA-32,称为x86-64(后来改名为AMD64)。其后也为英特尔所采用,现时英特尔称之为“Intel 64”,在之前曾使用过Clackamas Technology (CT)、IA-32e及EM64T。外界多使用"x86-64"或"x64"去称呼此64位架构,从而保持中立,不偏袒任何厂商。
AMD64代表AMD放弃了跟随Intel标准的一贯作风,选择了像把16位的Intel 8086扩充成32位的80386般,去把x86架构扩充成64位版本,且兼容原有标准。
AMD64架构在IA-32上新增了64位暂存器,并兼容早期的16位和32位软件,可使现有以x86为对象的编译器容易转为AMD64版本。除此之外,NX bit也是引人注目的特色之一。
不少人认为,像DEC Alpha般的64位RISC芯片,最终会取代现有过时及多变的x86架构。但事实上,为x86系统而设的应用软件实在太庞大,成为Alpha不能取代x86的主要原因,AMD64能有效地把x86架构移至64位的环境,并且能兼容原有的x86应用程序。
2006年出现了双核心多核心。多核心,也叫多微处理器核心是将两个或更多的独立处理器封装在一起的方案,通常在一个集成电路(IC)中。双核心设备只有两个独立的微处理器。一般说来,多核心微处理器允许一个计算设备在不需要将多核心包括在独立物理封装时执行某些形式的线程级并发处理(Thread-Level Parallelism,TLP)这种形式的TLP通常被认为是芯片级多处理。在游戏中你必须要使用驱动程序来利用第二颗核心。
此后处理器制造厂商发现,利用多核心架构可以在不提升处理器频率的情况下,继续不断提升处理器的效能。
2008年通用计算GPGPU。通用图形处理器(General-purpose computing on graphics processing units,简称GPGPU),是一种利用处理图形任务的图形处理器来计算原本由中央处理器处理的通用计算任务。这些通用计算常常与图形处理没有任何关系。由于现代图形处理器强大的并行处理能力和可编程流水线,令流处理器可以处理非图形数据。特别在面对单指令流多数据流(SIMD),且数据处理的运算量远大于数据调度和传输的需要时,通用图形处理器在性能上大大超越了传统的中央处理器应用程序。
3D显示卡的性能从NVIDIA的GeForce256时代就颇受瞩目,时间到了2008年,显示卡的计算能力开始被用在实际的计算当中。并且其处理的速度也远远超越了传统的x86处理器。
2010年CPU+GPU异构计算。对于GPGPU表现出的惊人计算能力叫人为之折服,但是在显卡进行计算的同时,处理器处于闲置状态。由此处理器厂商也想参与到计算中来,他们希望CPU和GPU能够协同运算,完成那些对计算量有着苛刻要求的应用。同时也希望将计算机的处理能力再推上一个新的高峰。
天河星云:异构计算大显神威
2009年,国际TOP500组织TOP500.org在网站上公布了全球超级计算机TOP500强排行榜,由国防科学技术大学研制,部署在国家超级计算天津中心,中国千万亿次超级计算机“天河一号”位居第一位,实测运算速度可以达到每秒2570万亿次。
“天河一号”耗资6亿元,连接了上万个美国英特尔和Nvidia公司制造的CPU和GPU,属异构混合架构。天河一号的配置是14336颗英特尔六核至强X5670 2.93GHz CPU和7168颗Nvidia Tesla M2050 GPU和2048颗自主研发的八核飞腾FT-1000 CPU。处理内核数突破20万颗,是2008年24576颗的8.25倍。
排名第三的是曙光公司研制的“星云”高性能计算机,其实测运算速度达到每秒1270万亿次。petaflop/s,千万亿次计算单位。星云系统峰值为每秒3000万亿次(3PFlops),实测Linpack值每秒1271万亿次(1.271PFlops),是中国第一台、世界第三台实测双精度浮点计算超千万亿次的超级计算机。
星云超级计算机采用自主设计的HPP体系结构,处理器是32nm工艺的六核至强X5650,并且采用了Nvidia Tesla C2050 GPU做协处理,由4640个计算单元组成。它采用了高效异构协同计算技术,系统包括了9280颗通用CPU和4640颗专用GPGPU组成。计算网络采用了单向40Gbps QDR Infiniband技术,核心存储采用了自主设计的Parastor高速I/O系统。
迥异:不同计算架构的特点
上文提到的采用的异构计算架构都属于大型计算机的范畴。对于个人计算机而言,尤其是x86架构的计算机,异构计算的步伐则要慢许多。这是因为,无论是处理器还是显示卡,又或者其他运算部件,都有其自身的架构和特性。他们是针对不同领域,面向不同应用所设计的芯片。所以他们在功能性方面千差万别。要想将他们都统一起来,除了需要制定共同的规范和标准之外,还要针对其计算的特点设计软件。
举例来说,CPU和GPU在进行计算时,就有许多不同。对于处理器来说,它是一颗通用处理器。它要应对各种类型的计算应用。无论是数学方面的,还是逻辑方面的运算。我们可以看到,一颗比较常规的处理器其中的ALU计算单元仅仅占据整个核心面积的25%以内。在处理器中,超过50%的核心面积用来制作Cache高速缓存,无论是L1、L2还是片上的L3。而另外还有25%的核心面积用来作为控制器。它控制着处理管线的运作,控制着各种分支预测,让多核心处理器可以更有效率。
而我们再反观GPU,其结构要简单的多。GPU的任务是加速3D像素的计算。因此我们在显卡中可以看到数以百计的流处理器单元或者是CUDA核心。而在整个计算过程中,GPU承担的逻辑计算任务非常小。同时它有着更宽的显存带宽,有着更高速的显存。所以在GPU芯片中,也就无需更大容量的片上缓存机制。
通过上文的分析,我们可以看到CPU的在处理时,适合作所有工作,各个方面都比较平均。逻辑处理能力要比GPU快,但是对于数学计算方面,其速度不如具有海量处理核心的GPU快。而GPU方面,数学计算性能强大,大规模并行处理机制强大,但是逻辑处理能力不足,仅仅能在某些计算领域应用。
异构计算芯片
AMD 2011年发布的新一代A8处理器,就是一颗真正意义上的异构计算处理器。AMD平台在CPU表现一直比较薄弱,如何把AMD显卡方面的优势均衡到CPU方面,AMD一直为这个目标而努力,而在AMD APU上,AMD已经初步实现了这个目的。这就是APU异构计算技术。
CPU的设计让其比较擅长于处理不规则数据结构和不可预测的存取模式,以及递归算法、分支密集型代码和单线程程序。这类程序任务拥有复杂的指令调度、循环、分支、逻辑判断以及执行等步骤。而GPU擅于处理规则数据结构和可预测存取模式。而APU的设计理念则正是让CPU和GPU完美合作,集合两者的长处,用异构计算来达到整体性能的最佳化。
这样的异构计算芯片可以充分发挥不同计算部件的优势。当需要进行较多逻辑计算时,可以使用CPU部分完成。当需要大量的浮点运算时,可以借用GPU的浮点运算处理管线来完成。同时如果处理器的某些核心正处于空闲,也可以让其加入到计算中来。由此可见异构计算不仅仅是需要统一起不同类型的计算部件,同时也需要有针对性的让更适合的硬件作适用的计算工作。
新的计算架构需要全新的软件标准
对于异构计算来说,更重要的软件。虽然现在我们看到许多计算机中都应用了GPGPU的通用计算,使用显卡来进行大规模的并行计算任务,但是在这个过程中,处理器就被闲置了。例如许多转码程序在运行的时候,仅仅是显卡在跑,而处理器并未参与到转码加速中来。将异构的运算部件,全部有效的调用起来,这是一件困难的编程工作。
OpenCL:无人能模仿 很难被超越
2008年6月的WWDC大会上,苹果提出了OpenCL规范,旨在提供一个通用的开放API,在此基础上开发GPU通用计算软件。随后,Khronos Group宣布成立GPU通用计算开放行业标准工作组,以苹果的提案为基础创立OpenCL行业规范。
OpenCL (Open Computing Language,开放计算语言) 是一个为异构平台编写程序的框架,此异构平台可由CPU,GPU或其他类型的处理器组成。OpenCL由一门用于编写kernels(在OpenCL设备上运行的函数)的语言(基于C99)和一组用于定义并控制平台的API组成。OpenCL提供了基于任务分区和数据分区的并行计算机制。
OpenCL类似于另外两个开放的工业标准OpenGL和OpenAL,这两个标准分别用于三维图形和计算机音频方面。OpenCL扩展了GPU用于图形生成之外的能力。OpenCL由非盈利性技术组织Khronos Group掌管。
OpenCL最初苹果公司开发,拥有其商标权,并在与AMD,IBM,英特尔和nVIDIA技术团队的合作之下初步完善。随后,苹果将这一草案提交至Khronos Group。2011年11月15日,OpenCL 1.2发布。
虽然苹果制定OpenCL的私心路人皆知,希望通过OpenGL来让自家的Mac电脑可以顺利的使用两个显卡巨头的产品做GPGPU运算。但是苹果的这一举措却为未来的x86平台异构计算奠定了坚实的基础。因为无论是CUDA还是FireStream,无论是CUDA核心还是流处理器,软件开发人员都可以通过OpenCL来支持。
C++ AMP:微软发布异构计算编程语言
Microsoft DirectCompute是一个应用程序接口(API),允许Windows Vista或Windows 7平台上运行的程序利用图形处理器(GPU)进行通用计算,DirectCompute是Microsoft DirectX的一部分。虽然DirectCompute最初在DirectX 11 API中得以实现,但支持DX10的GPU可以利用此API的一个子集进行通用计算,支持DX11的GPU则可以使用完整的DirectCompute功能。
相比OpenGL丰富的功能和体系化的SDK来说,DirectCompute仅仅是以一个简单的API存于世上,显然不能赢得更多厂商的关注。
自从AMD发布了Llano处理器,异构计算就真正进入了寻常百姓的家中。虽然OpenCL作为通用大规模并行计算的行业领军标准,得到了AMD、Intel、NVIDIA等芯片业巨头和大量行业厂商的支持,但唯独缺少了微软。
在2011年AMD Fusion(AFDS前身)开发者峰会上,微软终于拿出了自己的异构计算编程语言:“C++ AMP”,其中AMP三个字母是“accelerated massive parallelism”的缩写,也就是加速大规模并行的意思。
C++ AMP是微软Visual Studio和C++编程语言的新扩展包,用于辅助开发人员充分适应现在和未来的高度并行和异构计算环境。它使用C++语言的句法,将捆绑在下个版本的Visual Studio中发布,预计会在今年晚些时候放出测试版本。
为了与OpenCL相抗衡,微软宣布C++ AMP标准将是一种开放的规范,允许其它编译器集成和支持。这无疑是对OpenCL的最直接挑战。
Java Aparapi
Aparapi允许Java开发人员发挥GPU和APU设备的计算能力,通过在GPU上执行并行代码,可以获得远远超过只是用本地CPU计算的能力。
Java代码在运行时,Aparapi会先将字节码转换为OpenCL在GPU上执行。如果由于某种原因Aparapi不能在GPU上执行,它将会在Java线程池中运行。
一触即发:异构计算行业标准大战
OpenCL由多家主力厂商支持,技术纷争不断,为了自家产品的利益难免在新版本制定方面出现歧路。而微软的C++ AMP会与Windows紧密贴合起来。虽然也属于开放性的标准,但是微软对其未来方向的掌控,其执行应该更有效力。战国纷争,异构计算行业标准大战一触即发,不止异构计算未来鹿死谁手?