指令是软件和硬件交互的媒介。软硬件划分,其实就是确定“指令”复杂度的过程。通过“指令”复杂度,确定五个典型的计算平台:CPU、协处理器、GPU、FPGA和ASIC,依次“指令”复杂度越来越高,也依次从软件平台转向硬件平台。
1. 软件和硬件什么是软件?什么硬件?记得计算机入门课本中可以获取的通俗定义是这样的:计算机硬件看得见摸得着,而计算机软件则看不见摸不着。更详细严谨一些的定义是:
- 硬件指计算机的物理组件,可以看到和触摸的部分。如处理器、存储设备、监视器、打印机、键盘、鼠标等。
- 软件是在计算机系统上执行不同任务的说明,过程,文档的集合。我们也可以说计算机软件是在计算机处理器上执行的编程代码,该代码可以是裸机级别的代码,也可以是为操作系统编写的应用级别的代码。软件示例如Word、Chrome、Photoshop、MySQL等。
从上面的定义,我们可以看到软件和硬件的界限非常清楚,我们可以明确的知道哪些是软件,哪些是硬件。但是,当我们深入到底层的技术细节,却会发现:软件和硬件的界限并不完全清晰。
指令是计算机技术的核心概念,指令是送到处理器以执行动作的命令,指令集体系结构(ISA,Instruction Set Architecture)是处理器与软件程序进行交互的媒介。或者说,指令是CPU中软件和硬件交互的接口(区别于IO设备接口的软件和硬件处理的数据交互接口),我们编写的程序和相应的数据是软件,而支持软件运行的CPU和内存则是硬件。
我们定义了网卡、硬盘以及打印机等各种IO设备是硬件,但这些IO设备需要驱动及控制程序才能工作,并且IO设备内部也会有各种固件,才能保证设备正常工作。运行在CPU上的IO设备驱动及控制程序是软件,IO设备内部协调硬件工作的固件是软件。这其中,运行固件的载体必然是内部的某个嵌入式处理器和内部存储体(ROM、RAM等),而处理器和内存又是硬件。
2. 硬件加速的示例DES(Data Encryption Standard,数据加密标准)算法是一个非常经典的加密算法。以DES为例,MBire McLoone等人发表的《A High Performance Implementation of DES》文章中给出了一组数据,具体如 表1 所示。硬件加速器的性能是CPU软件性能的接近30倍,如果不考虑频率影响的话,性能对比则高达140倍。一次数据处理单位是64bits,软件实现(CPU执行指令的方式)的话,要完成一次DES,需要执行好几百条指令,一次64bits的处理需要大概140个时钟周期;专用加速器实现,一次64bits的DES处理却只需要1个时钟周期。
表1 DES算法CPU和硬件加速器对比
运行平台 | 频率 | 性能 | 性能对比 | 折算性能100MHz | 折算性能对比 |
Alpha 8400处理器 | 300MHz | 137Mb/s | 1 | 45.67Mb/s | 1 |
Xilinx Virtex XCV1000-4 BG560 | 60.5MHz | 3873.15Mb/s | 28.27 | 6402Mb/s | 140 |
另一个经典的例子就是近来非常火爆的比特币挖矿,比特币使用的技术区块链核心算法是SHA-256。它在各个平台上的性能对比如下:
- CPU:最开始的时候,大家使用CPU挖矿,一台高端个人电脑,处理速度大概20MH/s(H/s, Hash per second);
- GPU:后来有人用GPU加速挖矿,SHA-256可以继续拆分成普通的算术逻辑运算,而GPU具有超级多的算术逻辑运算单元,一个高端显卡的处理速度可以达到200MH/s;
- FPGA:再后来出现了定制SHA-256算法硬件逻辑的FPGA加速卡来挖矿,精心设计的定制电路的FPGA,可以使运算速度达到1GH/s;
- ASIC:而比特大陆公司2015年发布的ASIC矿机芯片BM1385,其性能达到单颗芯片算力可达32.5GH/s。
我们举个形象的例子:
- 团队A的每个工人可以在单位时间里加工5个零件,团队B的每个工人在单位时间里可以加工8个零件。
- 团队A的单位时间是3分钟,这意味着团队A一个小时可以有20个单位时间;团队B的单位时间是5分钟,这意味着团队B一个小时拥有12个单位时间。
- 团队A有10个人,团队B有20个人。
这意味着:在一个小时里,团队A可以完成1000个零件的加工,而团队B则可以完成1920个零件的加工。
衡量一个处理器的性能,需要通过三个维度:
- “指令”复杂度,类比于例子中单位时间加工的零件数量。指令复杂度,指的是单个指令计算量的密度。
- 运行速度,即运行频率,类比于例子中一个小时的单位时间数量,指的是1秒钟时钟周期的数量。
- 并行度,则类比于例子中团队的成员数量,指的是多个并行的处理。
CPU是硬件,基于CPU运行的程序是软件;GPU是硬件,基于GPU运行的程序是软件。那么CPU和GPU的差别在哪里?CPU我们一般也称为通用处理器,是相对于DSP(数字信号处理器)、GPU等概念所说的。CPU(不考虑协处理器)支持的指令称为通用指令,包括整形计算类、浮点类、数据传输类、控制类等。相比通用指令,一些复杂类指令(复杂类指令需要复杂的硬件逻辑来处理),则需要专用的硬件处理单元。比如SIMD(单指令流多数据流,Single Instruction Multiple Data)类和MIMD(多指令多数据流,Multiple Instruction Multiple Data)类指令,则可能是在GPU运行。
对硬件加速单元(Accelerator,从设计架构的角度也就是ASIC)来说,“指令”则是对算法的一次处理。例如在上节提到的DES算法设计,其“指令”为一次64bits DES计算。CPU对DES的一次处理需要上百条指令,而在DES硬件加速器这里,只需要一条“指令”,可见DES硬件加速器“指令”的复杂度远大于CPU指令的复杂度。
鱼和熊掌不可兼得,指令复杂度和编程灵活性是两个互反的特征:指令越简单,编程灵活性越高,因此我们才说软件有更高的灵活性;指令越复杂,性能越高,因此而受到的限制越多,只能用于特定场景的应用,其软件灵活性越差。
当我们通过定制硬件加速器的方式来获得性能提升,同时也就意味着放弃了软件应有的灵活性。
3.2 运行频率频率越高,计算速度越快。不考虑其他因素的制约,计算速度和频率是正比的关系。而频率受电路中的关键路径(延迟最大路径)约束,两者呈反比关系:关键路径越短,频率则越高。
如 图1 ,频率受关键路径制约,而关键路径与两个因素有关:
一个是关键路径所包含门的数量,即从前一级寄存器到后一级寄存器之间的最长路径所包含的逻辑门的数量;
另一个则是单个逻辑门的延迟时间,逻辑门的延迟时间跟半导体生产工艺相关,一般情况下,工艺尺寸越小,单个逻辑门的延迟越小。
(a) 组合电路示例
(b) 数字电路中的关键路径
图1 运行频率与电路逻辑的关系
当逻辑门的延迟越小,或者两级寄存器之间的逻辑门数量越少,则频率越高,计算速度也就越快。要想减小逻辑门延迟,就需要采用更先进的工艺;要想减少两级寄存器间逻辑门的数量,则需要采用更多级的流水,这样每一级流水所做的事情越少,所需要的逻辑门也就越少。
3.3 并行度并行的设计在硬件逻辑设计里非常常见。例如:
- 指令流水线:指令流水线是一种时间并行,在同时有多条指令处理流水线的不同阶段,这样相当于有多条指令在并行处理。
- 指令多发射(Multiple Issue):一条流水线,从指令缓冲区一次发送到译码阶段就有多条指令,然后在执行阶段也是多条指令并行。
- 超线程(Hyper-Thread):在一个处理器核内部,多组不同的指令流处理,分时的共享处理器核内部的各种硬件资源,达到更佳的资源利用率,提升整体性能。
- 多总线:例如,指令、数据总线分开,多数据总线等设计,进一步增加处理器的数据处理带宽。
- 多核技术:通过一些内部互联总线,把多个处理器核集成到一块芯片内,以此来提升综合性能。
- 多处理器芯片:受限于芯片工艺、功耗水平、设计架构,单芯片内的多核互联不能无限制增加下去,也可以通过一些芯片间互联技术,把多个CPU Socket连成一个NUMA系统,当前比较常见的是2-8个Socket互联的架构。
- 总线:对并行总线来说,增加数据线的宽度,对增加总线的带宽是显而易见的,并行总线一般用于芯片内部逻辑通信;串行总线,例如PCIe,相比PCI并行总线,一方面可以快速提升频率,还可以通过很多组串行线组合通信来提升传输性能,串行总线一般用于芯片间数据通信。
- 异构计算单元:CPU和GPU、xPU以及各种硬件加速器组成异构多处理单元共同协作完成工作任务,CPU更多的是承担控制和数据交互的角色。
- 多服务器集群:现在大型的互联网系统需要成百上千的服务器,分为业务处理、网络处理、存储和数据库处理等不同功能分工的服务器,共同组成一个性能强大并且运行稳定的系统对外提供服务。
通过不同方向、不同层次的并行技术,都可以提升硬件系统的性能。我们把不同复杂度的单位处理都当作了“指令”,那么,我们就可以通过IPC(Instruction per Cycle)来评价并行度。对一个CPU核来说,IPC代表的是每个周期执行的指令数;对一个硬件加速模块来说,IPC则代表了一个周期所能进行的单位处理的数量。
4. 综合分析我们通过“指令”复杂度、运行频率、并行度三个维度,对CPU、协处理器、GPU、FPGA和ASIC五种平台进行定性分析(受各种不同硬件平台和型号、不同架构实现、不同工艺的影响,很难对每个维度给出定量的分析数据),具体如 表2 所示。
表 2 CPU等各硬件平台性能定性分析
平台 | “指令”复杂度 | 运行频率 | 并行度 |
CPU | 通用指令集,最简单。指令越简单灵活性越大 | 极致优化的流水线,最高的运行频率 | 单核IPC一般为个位数 |
协处理器 | SIMD等扩展型指令,比通用指令要复杂 | 频率等于或低于处理器 | 一般情况下,并行度跟CPU在同一数量级 |
GPU | 类SIMD和MIMD/VLIW“指令”等,比协处理器指令复杂一些 | 受限于访存、指令计算的复杂度,频率一般低于CPU | 超多的线程,每个线程进行一次算术逻辑计算,可以有成百上千的并行度 |
FPGA | 完整算法的单位处理,复杂度远超通用指令 | 受限于FPGA硬件可编程,同工艺同设计下,一般运行频率ASIC的1/6左右 | 受资源限制,并行度比ASIC低 |
ASIC | “指令”复杂度和FPGA相当或超过FPGA复杂度 | 因为算法本身的复杂度,即使有流水线的实现,但运行频率依然会明显低于CPU | 资源规模大一些,一般会有比FPGA更多的并行度 |
如 图2 所示,我们可以看到,不同的硬件平台具有不同的灵活性和性能:
- CPU:通用指令的处理器,使用的指令复杂度最低,因此具有最高的灵活性,同时相对最差的性能。我们经常所说的某个任务或算法运行在软件,即指的是把任务或算法编程实现,然后在CPU执行。
- 协处理器:现代的处理器都会支持一些扩展指令集,例如Intel的AVX以及ARM的NEON等。这些指令集最终的计算是在一个扩展的执行模块里处理,一般把这些处理扩展指令集的部分称为协处理器。协处理器比CPU的灵活性稍微差一些,同时相比CPU,在一些特定场景能够提升性能,这种情况就是一种性能“加速”。例如,把Intel Xeon的AVX-512扩展指令集用于机器学习推理场景,可以获得比CPU明显的性能提升。
- GPU:图形处理单元,是一种并行架构设计,内部有上千个计算单元可以并行执行上千个线程。具有相对比较折中的灵活性和性能。由于图形计算中都是以向量计算为主,因此GPU对类SIMD/MIMD“指令”处理非常擅长。NVIDIA公司提供的CUDA计算框架降低了GPU软件开发的门槛,并且能够充分利用GPU的计算性能。
- FPGA:硬件可编程,一般实现特定的任务或算法加速器设计。从设计架构的角度,FPGA和ASIC是一致的。最主要的区别在于FPGA硬件可编程付出的代价是运行速度和硬件成本,但获得了硬件可编程的灵活性。
- ASIC:专用集成电路,实现特定的任务和算法。跟FPGA的区别是硬件电路是不可更改的。跟FPGA相比的优势是可以更高的频率和性能,但同时,ASIC具有所有硬件平台最差的灵活性,只能在特定应用场景发挥作用。
图2 CPU、协处理器、GPU、FPGA、ASIC不同硬件对比分析
从设计角度来看,FPGA和ASIC都会实现基于特定任务或算法处理的硬件加速模块,也就是我们通常所说的加速器。
100%的纯硬件没有意义,即使是硬件加速单元,依然离不开软件的参与,至少都需要软件驱动来初始化和配置模块,以此来控制模块的运行。而DSA是在ASIC基础上一定程度的“妥协”回调,在ASIC针对特定场景的基础上,定义了少量的指令,以此来提升ASIC的灵活性。DSA依然属于ASIC的范畴,当作是ASIC的特例,或者升级。