随着GPU的可编程性不断增强,GPU的应用能力已经远远超出了图形渲染任务,利用GPU完成通用计算的研究逐渐活跃起来,将GPU用于图形渲染以外领域的计算成为GPGPU(General Purpose computing on graphics processing units,基于GPU的通用计算)。而与此同时CPU则遇到了一些障碍,CPU为了追求通用性,将其中大部分晶体管主要用于构建控制电路(比如分支预测等)和Cache,只有少部分的晶体管来完成实际的运算工作。
CPU + GPU 是一个强大的组合,因为 CPU 包含几个专为串行处理而优化的核心,而 GPU 则由数以千计更小、更节能的核心组成,这些核心专为提供强劲的并行性能而设计。程序的串行部分在 CPU 上运行,而并行部分则在 GPU上运行。GPU 已经发展到成熟阶段,可轻松执行现实生活中的各种应用程序,而且程序运行速度已远远超过使用多核系统时的情形。未来计算架构将是并行核心 GPU 与多核 CPU 共同运行的混合型系统。
一、CPU多核转到GPU并行化(适合算术密集型)
虽然GPU并不适用于所有问题的求解,但是我们发现那些对运算力量耗费巨大的科学命题都具备天然的“”特色。这类程序在运行时拥有极高的运算密度、并发线程数量和频繁地存储器访问,无论是在音频处理、视觉仿真还是到分子动力学模拟和金融风险评估领域都有大量涉及。这种问题如果能够顺利迁移到GPU为主的运算环境中,将为我们带来更高效的解决方案。
传统意义上的GPU不善于运行分支代码,但是ATI和NVIDIA经过长期改进其内部架构已经使得GPU可以较为高效地运行分支、循环等复杂代码。同时因为GPU属于并行机范畴,相同的运算可以应用到每个数据元素的时候,它们可以达到最好的性能。在CPU编程环境中,写出每个输入数据元素有不同数量的输入的程序很容易,但在GPU这种并行机上还是有不少麻烦。
通用的数据结构正是GPU编程的最大困难之一。CPU程序员经常使用的数据结构如列表和树在GPU身上并不容易实现。GPU目前还不允许任意存储器访问,而且GPU运算单元的设计为主要操作是在表现位置和颜色的四维向量上。
不过这些并不能阻挡GPU编程的加速发展,因为GPU不是真的为通用计算而设计的,需要一些努力才能让GPU高速地服务通用计算程序。这些努力前些年是程序员而单独实现的,而随着ATI和NVIDIA开始看到高性能计算市场的硬件需求,我们看到无论是Fermi架构添加全能二级缓存和统一定址还是RV870架构不断优化LDS并放大并发线程数,这些都是GPU自身硬件体系为了适应未来的运算环境而做出的变革。
二、并行化编程优点
在GPU并行编程过程中,OpenCL是一个不错的选择。OpenCL是Open Computing Language(开放式计算语言)的简称,它是第一个为异构系统的通用并行编程而产生的统一的、免费的标准。OpenCL支持由多核的CPU、GPU、Cell类型架构以及信号处理器(DSP)等其他的并行设备组成的异构系统。OpenCL的出现,使得软件开发人员编写高性能服务器、桌面计算系统以及手持设备的代码变得更加快捷。OpenCL由用于编写内核程序的语言和定义并控制平台的API组成,提供了基于任务和基于数据的两种并行计算机制,使得GPU的计算不在仅仅局限于图形领域,而能够进行更多的并行计算。但是,如果通过传统的方法开发一个能够运行在异构平台(在CPU和GPU的平台)的程序是很难的。不同的厂商,不同的产品型号的GPU一般有着不一样的架构,这样要想开发出一款能够高效的能够运用不同平台的所有计算资源的软件是很难的。OpenCL的出现有效地解决了异构平台的问题。
OpenCL规范是由Khronos Group推出的,OpenCL程序不仅仅可以运行在多核的CPU上,也可以在GPU上进行执行,这充分体现了OpenCL的跨平台性和可移植性,也让编程人员可以充分利用GPU的强大的并行计算能力,相对于CPU来说,GPU存在很多特点。
l GPU拥有的核心的数量要比高端CPU的核心数量多很多。虽然GPU的每个运算核心没有CPU的每个运算核心工作频率高,但是GPU的总体性能-芯片面积比以及性能-功耗比比CPU高很多,所以在处理越多线程的并行计算的任务性能高很多。
l GPU能够通过大量并行线程之间的交织运行隐藏全局的延迟,除此之外GPU还拥有大量的寄存器、局部存储器和cache等用来提升外部存储的访问性能。
l 在传统的CPU运算中,线程之间的切换是需要很大的开销的,所以在开启了大量线程的算法的效率是很低的。但是,在GPU中,线程之间的切换是很廉价的。
l GPU的计算能力比CPU强很多。
三、OpenCL环境下并行化编程
OpenCL是一个开放的工业标准,它可以为CPU和GPU等不同的设备组成的异构平台进行编程。OpenCL是一种语言,也是一个为并行编程而提供的框架,编程人员可以利用OpenCL编写出一个能够在GPU上执行的通用程序。
OpenCL的技术核心包好了下面的四种模型:
l 平台模型(Platform Model):OpenCL平台模型定义了主机和设备的角色,为程序员写在设备上执行的OpenCL C函数(内核)提供了一个抽象的硬件模型。平台模型确定了主机上的处理器能够协调执行,而且存在一个或者多个处理器能够执行OpenCL C代码(设备)。
l 执行模型(Execution Model):定义如何在主机上配置OpenCL环境以及内核(kernel)是如何在设备上执行的。这其中包括在主机上设置OpenCL上下文,提供主机和设备交互的机制,定义了内核在设备上执行的兵法模式。
l 内存模型(Memory Model):定义了内核使用的抽象的内存层次。
l 编程模型(Programming Model):定义了并发模型如何让映射到物理硬件。
OpenCL框架被分成平台层API和运行时API,平台层API允许应用查询平台和设备,而且可以通过上下文来管理它们。运行时的API利用上下文去管理设备上的内核的执行。
四、OpenCL并行化调试工具
在利用OpenCL进行编程之后,我们可以使用gDEBugger进行调试,gDEBugger是一个高级的OpenCL和OpenGL调试器,分析器和内存分析器。它可以完成其他工具无法完成的工作:追踪在OpenCL和OpenGL之上的应用程序的活动,并发现系统实现的内部发生了什么。
程序员可以在以下的情况下使用gDEBugger
l 优化OpenCL和OpenGL应用程序性能。
l 快速找到与OpenCL和OpenGL相关的bug。
l 改善程序性能和鲁棒性
五、CPU和GPU共享记忆体空间
在过去的时间,虽然GPU和CPU已整合到同一个晶片上(GPGPU技术),但是晶片在运算时要定位记忆体的位置仍然得经过繁杂的步骤,这是因为CPU和GPU的记忆体池仍然是独立运作。之前为了解决两者记忆体池独立的运算问题,当CPU程式需要在GPU上进行部分运算时,CPU都必须从CPU的记忆体上复制所有的资料到GPU的记忆体上,而当GPU上的运算完成时,这些资料还得再复制回到CPU记忆体上。这些步骤都会不断耗费时间以及程式处理的效能。2012年,AMD就携手ARM、高通、三星、联发科等厂商成立HSA(Heterogeneous
Systems Architecture)基金会,希望拓展CPU和GPU协同运算的新架构,并辅助此架构发展的异质运算新软体开发环境。
日前,AMD进一步公开说明此运算架构的新技术:hUMA(heterogeneous Uniform Memory Access)。透过hUMA,CPU和GPU能共享同一个记忆体空间,并且CPU能够直接存取GPU的记忆体位址,不必像过去得花工夫再将GPU的运算资料复写到CPU上。近日,在HotChips会议上,AMD连续公布了桌面FX处理器使用的Steamroller架构、面向低功耗平台的Jaguar架构等,但是这都不是AMD的终极目标,他们声称处理器速度的竞争已经结束,未来属于HSA。
六、未来发展趋势
在计算机发展历程中,为了解决各种特定的问题,不断有互不兼容的计算模块被加入系统,却很少从全局优化的角度加以考察。计算机整体效率不高的现状正是这种设计模式的直接后果。常见情况是软件的计算负载被调度在一个并不适合当前任务的计算设备上低效执行。HSA则展现了一种全新的体系架构,可以适应各种特性的计算任务。
HSA版本可以在CPU和GPU之间无缝地共享数据,而无需内存拷贝和缓存刷新,因为任务以极低的开销被调度到合适的处理器上。最终的结果是HSA版本的性能高出2.3倍,而功耗降低2.4倍*。相较而言,无论是多核CPU、GPU、甚至非HSA方式的混合CPU和GPU都无法达到这样的性能水平。同样重要的是,无需转换到迥异的编程模型,仅仅通过C++的简单扩展就可以实现程序。