经常会遇到一些人问我什么是FPGA,它与集成电路有什么关系2?它与我们熟知的CPU,GPU又有什么区别?这里我试着以我个人的理解对这些问题进行一个简单的介绍。
所谓集成电路就是将之前使用各种分立元器件(比如电阻,二极管,三极管等) 搭建的电路集成到一块芯片上就称之为集成电路。集成电路对于离散晶体管有成本和性能方面的优势。所以集成电路迅速的替代了离散晶体管电路。而根据处理信号的不同,集成电路可以分为模拟集成电路、数字集成电路、和兼具模拟与数字的混合信号集成电路。FPGA(现场可编程门阵列)主要是处理数字信号(虽然最新的FPGA已集成部分模拟电路,但是FPGA总的功能主要还是在处理数字信号。)
FPGA与一般的数字集成电路有什么区别呢?
在数字集成电路的世界里,信号只有0和1两个状态,就是我们所谓的二进制。比如高电平就是1,低电平就是0。数字电路有一些基本的门电路,比如与门,或门,非门。我们通过一些简单的与,或,非操作就可以实现各种数字计算功能。数字电路分析经常会用到真值表,如下所示:
当输入信号A为0,B为0时,或门的输出为0,与非门的输出为1,与或门的输出为0.由这些简单的门电路来实现一些复杂的功能。举个例子,要实现一个加法器,输入信号分别是A和B。A和B分别为1bit的数字信号,结果是C。C为一个2bit的数字信号,如何来实现这个加法器呢?该计算的真值表如下:
在实际中,因为涉及到多位数的运算,所以不得不考虑进位,那么半加器就不能满足我们的需求了,所以我们要做一个全加器。所谓全加器,就是对二进制执行加法运算的电路,考虑进位。我们来分析分析。
我们直接给出全加器的电路,请读者根据真值表来分析
我们可以使用2个半加器来实现一个全加器。
要实现八位加法器,当然就要八个全加器,只不过第一个全加器的进位输入值我们设为0就好啦。
这就是八位加法器,进位输入我们设置为0,然后A,B就是我要进行加法运算的8bits的二进制数啦。 按照这种思路,我们也可以设计出16位,32位的加法器。
由以上几个例子可以看出,我们可以通过这几种基本电路实现很多很复杂的电路。这是就通常所说的专用集成电路(Application-specific integrated circuit)。专用集成电路的缺点是我们要实现任何专用的功能,都需要芯片设计,验证,生产,测试等很复杂的流程。
FPGA使用了一个更加巧妙的方法来实现各种电路功能。比如上面的8位加法器,输入为2个8bit的数字,输出为一个9bit的数字。FPGA使用一种叫做查找表的方式来实现这个功能,查找表相当于一个存储器,我们通过编译软件,将16bit输入不同情况下的输出提前计算出来,存储到查找表中,当输入信号确定以后,只需查表就可以知道输出的结果。优点是查找表可以实现任何功能,由软件将不同输入情况下的各种结果都提前算出来,存储到查找表中。
FPGA的另外一个优点就是延迟可控。就像8位加法器,后面的输出依赖于前面的计算,前面的计算结束以后才能进行后面的计算,加法器位宽越宽,延迟越大。对于查找表则不存在这个问题。
FPGA的这些优点也是有代价的。首先使用FPGA会有资源浪费,我们不可能使用FPGA的所有资源。就像一块面包板一样,我们不可能完全使用它。当然FPGA厂商不断的在优化他们的算法,尽可能的将FPGA的潜能都利用起来。比如设计一个加法器需要使个逻辑门电路,但是使用FPGA,或许你需要选择拥有1000个逻辑门的芯片。这些冗余的逻辑资源使得FPGA的成本比较高,而且即使不使用的逻辑资源也会有漏电流,所以FPGA的功耗会高于专用集成电路。还有因为FPGA要兼顾灵活性,所以设计不一定会最优,进而影响到设计的性能。比如专用集成电路很容易运行到上GHz,但是FPGA的设计通常都是运行在几百MHz。
现在的芯片都变得越来越复杂,大家为了在一颗芯片上集成更多的电路,往往倾向于采用更加先进的制造工艺。但是先进的制造工艺意味着越来越高的一次流片成本。而对于数字电路设计来说,通常都是有verilog或者VHDL等硬件描述语言,这些设计方法对于专用集成电路和FPGA来说是相同的。所以更多数字芯片设计厂商会利用FPGA来进行原型验证。当自己的设计在FPGA上验证成功,设计最终定型,并且生产量比较大,很多厂商会考虑将FPGA设计转为专用集成电路。经过优化的专用集成电路或具有更小的芯片体积,随着产量的提高,单颗芯片的成本也会大幅下降。
这是从芯片设计角度来说的。FPGA的另外一个重要应用领域就是高性能计算。在高性能计算领域,主要的竞争对手是CPU和GPU。我们接下来谈一谈CPU,GPU与FPGA又有什么区别。
CPU介绍
FPGA是可编程器件,可以更为大家熟知的可编程器件是CPU(中央处理器)。中央处理器主要包括运算器(算术逻辑运算单元,ALU,Arithmetic Logic Unit)和高速缓冲存储器(Cache)及实现它们之间联系的数据(Data)、控制及状态的总线(Bus)。它与内部存储器(Memory)和输入/输出(I/O)设备合称为电子计算机三大核心部件。CPU又是怎么样工作的呢?
前面提到,任何一个复杂的工作都可以分解为很多很简单的步骤,要运行在CPU上的程序也是经过编译器,将我们写的程序转化为CPU可以执行的几种简单指令。不同体系的CPU有不同的指令集。这些指令集列举了这些CPU可以执行的指令。CPU的运作原理可分为四个阶段:提取、解码、执行和写回。
第一阶段,提取,从存储器或高速缓冲存储器中检索指令(为数值或一系列数值)。由程序计数器(Program Counter)指定存储器的位置。(程序计数器保存供识别程序位置的数值。换言之,程序计数器记录了CPU在程序里的踪迹。)
CPU根据存储器提取到的指令来决定其执行行为。在解码阶段,指令被拆解为有意义的片段。根据CPU的指令集架构(ISA)定义将数值解译为指令。一部分的指令数值为运算码(Opcode),其指示要进行哪些运算。其它的数值通常供给指令必要的信息,诸如一个加法(Addition)运算的运算目标。
在提取和解码阶段之后,紧接着进入执行阶段。该阶段中,连接到各种能够进行所需运算的CPU部件。
例如,要求一个加法运算,算术逻辑单元(ALU,Arithmetic Logic Unit)将会连接到一组输入和一组输出。输入提供了要相加的数值,而输出将含有总和的结果。ALU内含电路系统,易于输出端完成简单的普通运算和逻辑运算(比如加法和位元运算)。如果加法运算产生一个对该CPU处理而言过大的结果,在标志暂存器里可能会设置运算溢出(Arithmetic Overflow)标志。
最终阶段,写回,以一定格式将执行阶段的结果简单的写回。运算结果经常被写进CPU内部的暂存器,以供随后指令快速存取。在其它案例中,运算结果可能写进速度较慢,但容量较大且较便宜的主记忆体中。某些类型的指令会操作程序计数器,而不直接产生结果。这些一般称作“跳转”(Jumps),并在程式中带来循环行为、条件性执行(透过条件跳转)和函式。许多指令会改变标志暂存器的状态位元。这些标志可用来影响程式行为,缘由于它们时常显出各种运算结果。例如,以一个“比较”指令判断两个值大小,根据比较结果在标志暂存器上设置一个数值。这个标志可借由随后跳转指令来决定程式动向。在执行指令并写回结果之后,程序计数器值会递增,反复整个过程,下一个指令周期正常的提取下一个顺序指令。
CPU的ALU等部件都是专用电路,进行了专门的优化,所以CPU通常可以跑到很高的速度。而且CPU中有比较器等专用计算单元,CPU很适合有很多判断的应用场景,也就是通常所说的控制部分。
CPU的缺点就是只有几个数量有限的算术逻辑单元,而且每次指令都要有相应的指令读取,结果存储等步骤。而往往高速缓存的读取和存储也是限制CPU性能的重要方面。举个例子,把CPU看做一个工厂,CPU有有限的几个能力很强的工人,这些工人做事情很快。问题是工人数量有限,而且工人每次要把货物搬到自己的操作台,操作完成后又要把货物搬离自己的操作台。
GPU是图形处理器的简称。大家熟知的GPU就是我们通常俗成为显卡的东西,是为了视频游戏而产生的(至今其主要驱动力还是不断增长视频游戏市场),在三维游戏中常常出现的一类操作是对海量数据进行相同的操作,如:对每一个顶点进行同样的坐标变换,对每一个顶点按照同样的光照模型计算颜色值。GPU的众核架构非常适合把同样的指令流并行发送到众核上,采用不同的输入数据执行。在2003-2004年左右,图形学之外的领域专家开始注意到GPU与众不同的计算能力,开始尝试把GPU用于通用计算(即GPGPU)。之后NVIDIA发布了CUDA,AMD和Apple等公司也发布了OpenCL,GPU开始在通用计算领域得到广泛应用,包括:数值分析,海量数据处理(排序,Map-Reduce等),金融分析等等。
GPU和CPU有很多相同之处:两者都有总线和外界联系,有自己的缓存体系,以及数字和逻辑运算单元。一句话,两者都为了完成计算任务而设计。
两者的区别在于存在于片内的缓存体系和数字逻辑运算单元的结构差异:CPU虽然有多核,但总数没有超过两位数,每个核都有足够大的缓存和足够多的数字和逻辑运算单元,并辅助有很多加速分支判断甚至更复杂的逻辑判断的硬件;GPU的核数远超CPU,被称为众核(NVIDIA Fermi有512个核)。每个核拥有的缓存大小相对小,数字逻辑运算单元也少而简单(GPU初始时在浮点计算上一直弱于CPU)。简单来说,GPU就是海量精简版的CPU的集合。GPU采用SIMD(Single Instruction Multiple Data)架构。就是说海量的GPU上运行相同的指令,这样就减少了指令的读取,同时将大量数据的读取操作进行合并,大幅提升数据读取效率。
CPU擅长处理具有复杂计算步骤和复杂数据依赖的计算任务,如分布式计算,数据压缩,人工智能,物理模拟,以及其他很多很多计算任务等。GPU更适合处理处理海量数据,数据之间没有相互依赖关系,相对独立,GPU可以对大量数据进行并行计算。
形象的比喻,GPU的工厂里有大量工人,每个工人的能力都不是很强,他们都做相同的事情,每个工人的工作没有直接的关系。
FPGA适合于应用到CPU和GPU折中的应用中。即数量并行量不是那么大,判断不是那么多的应用。FPGA适合深度的流水线算法。前一个计算单元的计算结果直接进入下一个逻辑运算单元。FPGA还适用于MISD的应用,即单一数据需要用许多条指令平行处理,这种情况下用FPGA做一个MISD的架构就会比GPU有优势。
另外,相较于高性能的CPU以及GPU,FPGA的功耗就显得小很多。
下一篇