什么是异构并行计算?CPU与GPU的区别是什么?

01、先了解什么是异构并行计算

同构计算是使用相同类型指令集和体系架构的计算单元组成系统的计算方式。

而异构计算主要是指使用不同类型指令集和体系架构的计算单元组成系统的计算方式,常见的计算单元类别包括CPU、GPU、DSP、ASIC、FPGA等。

异构计算用简单的公式可以表示为“CPU+XXX”。

由于术业有专攻,CPU、GPU、DSP、ASIC、FPGA各有所长,在一些场景下,引入特定计算单元,让计算系统变成混合结构,就能让CPU、GPU、DSP、FPGA执行自己最擅长的任务。

异构计算(Heterogeneous Computing)在80年代中期就已产生,其定义更加宽泛。异构计算主要是指使用不同类型指令集和体系架构的计算单元组成系统的计算方式。常见的计算单元类别包括CPU、GPU等协处理器、DSP、ASIC、FPGA等。一个异构计算平台往往包含使用不同指令集架构(ISA)的处理器。

从软件的角度来讲,异构并行计算框架是让软件开发者高效地开发异构并行的程序,充分使用计算平台资源。从硬件角度来讲,一方面,多种不同类型的计算单元通过更多时钟频率和内核数量提高计算能力,另一方面,各种计算单元通过技术优化(如GPU从底层架构支持通用计算,通过分支预测、原子运算、动态并行、统一寻址、NIC直接访问显存等能力)提高执行效率。

正是因为异构计算在理论上有着诸多的优势,一些媒体将“CPU+XXX”称为下一代处理器。

异构计算在理论上相对于同构计算拥有很多优势——HSA能够简化芯片结构设计、降低应用编程门槛、缩短项目研发周期、显著提升芯片性能、广泛共享软件生态。

有厂家甚至宣传异构计算可以实现任何程序都不必费心考虑不同处理器内核之间的存储差异。但在现阶段,异构计算除了在超算上取得了明显成绩,在其他领域优势并不大。

即便异构计算目前还存在这样或那样的一些问题,但却是非常具有发展潜力的技术。

随着技术的进步,电子消费品市场对于高性能并行计算的需求正在爆发性增长,特别是在机器视觉、人工智能、云计算、AR/VR、软件定义无线电以及其他新兴领域,都对异构计算系统有着非常大的需求。

而HSA在系统编程方式上的迈进使得一个复杂片上系统能够协调在并行计算上比CPU更高效、更低功耗的GPU、DSP以及硬件加速器等计算单元承担大部分繁重的计算工作任务,在上述新兴领域能发挥较理想的作用。

Imagination也在异构计算领域积极布局......可以说,异构计算的市场前景还是值得期待。

02、CPU与GPU的区别

随着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 共同运行的混合型系统。

1. CPU即中央处理器

CPU( Central Processing Unit, 中央处理器)就是机器的“大脑”,也是布局谋略、发号施令、控制行动的“总司令官”。

CPU的结构主要包括运算器(ALU, Arithmetic and Logic Unit)、控制单元(CU, Control Unit)、寄存器(Register)、高速缓存器(Cache)和它们之间通讯的数据、控制及状态的总线。

简单来说就是:计算单元、控制单元和存储单元,架构如下图所示:

CPU微架构示意图
图:CPU微架构示意图

从字面上我们也很好理解,计算单元主要执行算术运算、移位等操作以及地址运算和转换;存储单元主要用于保存运算中产生的数据以及指令等;控制单元则对指令译码,并且发出为完成每条指令所要执行的各个操作的控制信号。

所以一条指令在CPU中执行的过程是这样的:读取到指令后,通过指令总线送到控制器(黄色区域)中进行译码,并发出相应的操作控制信号;然后运算器(绿色区域)按照操作指令对数据进行计算,并通过数据总线将得到的数据存入数据缓存器(大块橙色区域)。过程如下图所示:

CPU执行指令图
图:CPU执行指令图

CPU遵循的是冯诺依曼架构,其核心就是:存储程序,顺序执行。在这个结构图中,负责计算的绿色区域占的面积似乎太小了,而橙色区域的缓存Cache和黄色区域的控制单元占据了大量空间。

因为CPU的架构中需要大量的空间去放置存储单元(橙色部分)和控制单元(黄色部分),相比之下计算单元(绿色部分)只占据了很小的一部分,所以它在大规模并行计算能力上极受限制,而更擅长于逻辑控制。

另外,因为遵循冯诺依曼架构(存储程序,顺序执行),CPU就像是个一板一眼的管家,人们吩咐的事情它总是一步一步来做。但是随着人们对更大规模与更快处理速度的需求的增加,这位管家渐渐变得有些力不从心。

于是,能不能把多个处理器放在同一块芯片上,让它们一起来做事,这样效率不就提高了吗?GPU便由此诞生了。

2. GPU即图形处理器

GPU全称为Graphics Processing Unit,中文为图形处理器,就如它的名字一样,GPU最初是用在个人电脑、工作站、游戏机和一些移动设备(如平板电脑、智能手机等)上运行绘图运算工作的微处理器。

为什么GPU特别擅长处理图像数据呢?这是因为图像上的每一个像素点都有被处理的需要,而且每个像素点处理的过程和方式都十分相似,也就成了GPU的天然温床。

GPU简单架构如下图所示:

GPU微架构示意图
图:GPU微架构示意图

从架构图我们就能很明显的看出,GPU的构成相对简单,有数量众多的计算单元和超长的流水线,特别适合处理大量的类型统一的数据。

但GPU无法单独工作,必须由CPU进行控制调用才能工作。CPU可单独作用,处理复杂的逻辑运算和不同的数据类型,但当需要大量的处理类型统一的数据时,则可调用GPU进行并行计算。

注:GPU中有很多的运算器ALU和很少的缓存cache,缓存的目的不是保存后面需要访问的数据的,这点和CPU不同,而是为线程thread提高服务的。如果有很多线程需要访问同一个相同的数据,缓存会合并这些访问,然后再去访问dram。

再把CPU和GPU两者放在一张图上看下对比,就非常一目了然了。


GPU的工作大部分都计算量大,但没什么技术含量,而且要重复很多很多次。

借用知乎上某大神的说法,就像你有个工作需要计算几亿次一百以内加减乘除一样,最好的办法就是雇上几十个小学生一起算,一人算一部分,反正这些计算也没什么技术含量,纯粹体力活而已;而CPU就像老教授,积分微分都会算,就是工资高,一个老教授顶二十个小学生,你要是富士康你雇哪个?

GPU就是用很多简单的计算单元去完成大量的计算任务,纯粹的人海战术。这种策略基于一个前提,就是小学生A和小学生B的工作没有什么依赖性,是互相独立的。

有一点需要强调,虽然GPU是为了图像处理而生的,但是我们通过前面的介绍可以发现,它在结构上并没有专门为图像服务的部件,只是对CPU的结构进行了优化与调整,所以现在GPU不仅可以在图像处理领域大显身手,它还被用来科学计算、密码破解、数值分析,海量数据处理(排序,Map-Reduce等),金融分析等需要大规模并行计算的领域。

所以GPU也可以认为是一种较通用的芯片。

从根本上说CPU和GPU它们的目的不同,且有不同侧重点,也有着不同的性能特性,在某些工作中CPU执行得更快,另一工作中或许GPU能更好。当你需要对大量数据做同样的事情时,GPU更合适,当你需要对同一数据做很多事情时,CPU正好。

然而在实际应用中,后一种情形更多,也就是CPU更为灵活能胜任更多的任务。GPU能做什么?关于图形方面的以及大型矩阵运算,如机器学习算法、挖矿、暴力破解密码等,GPU会大幅提高计算效率。


Cache, local memory:CPU > GPU
Threads(线程数): GPU > CPU
Registers: GPU > CPU 多寄存器可以支持非常多的Thread,thread需要用到register,thread数目大,register也必须得跟着很大才行。
SIMD Unit(单指令多数据流,以同步方式,在同一时间内执行同一条指令): GPU > CPU。

简单地说,CPU擅长分支预测等复杂操作,GPU擅长对大量数据进行简单操作。一个是复杂的劳动,一个是大量并行的工作。

其实GPU可以看作是一种专用的CPU,专为单指令在大块数据上工作而设计,这些数据都是进行相同的操作,要知道处理一大块数据比处理一个一个数据更有效,执行指令开销也会大大降低,因为要处理大块数据,意味着需要更多的晶体管来并行工作,现在旗舰级显卡都是百亿以上的晶体管。

CPU呢,它的目的是尽可能快地在单个数据上执行单个指令。由于它只需要使用单个数据单条指令,因此所需的晶体管数量要少得多,目前主流桌面CPU晶体管都是十亿以下,和顶级GPU相差十倍以上,但它需要更大的指令集,更复杂的ALU(算术逻辑单元),更好的分支预测,更好的虚拟化架构、更低的延迟等等。

总而言之,CPU和GPU因为最初用来处理的任务就不同,所以设计上有不小的区别。CPU的运算速度取决于请了多么厉害的教授。教授处理复杂任务的能力是碾压小学生的,但是对于没那么复杂的任务,还是顶不住人多。当然现在的GPU也能做一些稍微复杂的工作了,相当于升级成初中生高中生的水平。但还需要CPU来把数据喂到嘴边才能开始干活,最终还是靠CPU来管的。

03、CPU+GPU并行计算的好处

1. CPU多核转到GPU并行化(适合算术密集型)

虽然GPU并不适用于所有问题的求解,但是我们发现那些对运算力量耗费巨大的科学命题都具备天然的特色。这类程序在运行时拥有极高的运算密度、并发线程数量和频繁地存储器访问,无论是在音频处理、视觉仿真还是到分子动力学模拟和金融风险评估领域都有大量涉及。这种问题如果能够顺利迁移到GPU为主的运算环境中,将为我们带来更高效的解决方案。

通用的数据结构正是GPU编程的最大困难之一。CPU程序员经常使用的数据结构如列表和树在GPU身上并不容易实现。GPU目前还不允许任意存储器访问,而且GPU运算单元的设计为主要操作是在表现位置和颜色的四维向量上。

不过这些并不能阻挡GPU编程的加速发展,因为GPU不是真的为通用计算而设计的,需要一些努力才能让GPU高速地服务通用计算程序。这些努力前些年是程序员而单独实现的。

2. 并行化编程优点

在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存在很多特点。

GPU拥有的核心的数量要比高端CPU的核心数量多很多。虽然GPU的每个运算核心没有CPU的每个运算核心工作频率高,但是GPU的总体性能-芯片面积比以及性能-功耗比比CPU高很多,所以在处理越多线程的并行计算的任务性能高很多。

GPU能够通过大量并行线程之间的交织运行隐藏全局的延迟,除此之外GPU还拥有大量的寄存器、局部存储器和cache等用来提升外部存储的访问性能。

在传统的CPU运算中,线程之间的切换是需要很大的开销的,所以在开启了大量线程的算法的效率是很低的。但是,在GPU中,线程之间的切换是很廉价的。

GPU的计算能力比CPU强很多。

3. OpenCL环境下并行化编程

OpenCL是一个开放的工业标准,它可以为CPU和GPU等不同的设备组成的异构平台进行编程。OpenCL是一种语言,也是一个为并行编程而提供的框架,编程人员可以利用OpenCL编写出一个能够在GPU上执行的通用程序。

OpenCL的技术核心包好了下面的四种模型:
平台模型(Platform Model):OpenCL平台模型定义了主机和设备的角色,为程序员写在设备上执行的OpenCL C函数(内核)提供了一个抽象的硬件模型。平台模型确定了主机上的处理器能够协调执行,而且存在一个或者多个处理器能够执行OpenCL C代码(设备)。

执行模型(Execution Model):定义如何在主机上配置OpenCL环境以及内核(kernel)是如何在设备上执行的。这其中包括在主机上设置OpenCL上下文,提供主机和设备交互的机制,定义了内核在设备上执行的兵法模式。

内存模型(Memory Model):定义了内核使用的抽象的内存层次。

编程模型(Programming Model):定义了并发模型如何让映射到物理硬件。

OpenCL框架被分成平台层API和运行时API,平台层API允许应用查询平台和设备,而且可以通过上下文来管理它们。运行时的API利用上下文去管理设备上的内核的执行。

4. OpenCL并行化调试工具

在利用OpenCL进行编程之后,我们可以使用gDEBugger进行调试,gDEBugger是一个高级的OpenCL和OpenGL调试器,分析器和内存分析器。它可以完成其他工具无法完成的工作:追踪在OpenCL和OpenGL之上的应用程序的活动,并发现系统实现的内部发生了什么。

程序员可以在以下的情况下使用gDEBugger:
优化OpenCL和OpenGL应用程序性能。
快速找到与OpenCL和OpenGL相关的bug。
改善程序性能和鲁棒性

5. CPU和GPU共享记忆体空间

在过去的时间,虽然GPU和CPU已整合到同一个晶片上(GPGPU技术),但是晶片在运算时要定位记忆体的位置仍然得经过繁杂的步骤,这是因为CPU和GPU的记忆体池仍然是独立运作。之前为了解决两者记忆体池独立的运算问题,当CPU程式需要在GPU上进行部分运算时,CPU都必须从CPU的记忆体上复制所有的资料到GPU的记忆体上,而当GPU上的运算完成时,这些资料还得再复制回到CPU记忆体上。

这些步骤都会不断耗费时间以及程式处理的效能。

6. 未来发展趋势

在计算机发展历程中,为了解决各种特定的问题,不断有互不兼容的计算模块被加入系统,却很少从全局优化的角度加以考察。计算机整体效率不高的现状正是这种设计模式的直接后果。常见情况是软件的计算负载被调度在一个并不适合当前任务的计算设备上低效执行。HSA则展现了一种全新的体系架构,可以适应各种特性的计算任务。

HSA版本可以在CPU和GPU之间无缝地共享数据,而无需内存拷贝和缓存刷新,因为任务以极低的开销被调度到合适的处理器上。最终的结果是HSA版本的性能高出2.3倍,而功耗降低2.4倍。相较而言,无论是多核CPU、GPU、甚至非HSA方式的混合CPU和GPU都无法达到这样的性能水平。同样重要的是,无需转换到迥异的编程模型,仅仅通过C++的简单扩展就可以实现程序。

来源:电子工程技术 - 苏小喵
https://mp.weixin.qq.com/s/kn9TRubf_lihorFQt8fhuQ

最新文章