《电子技术应用》
您所在的位置:首页 > 可编程逻辑 > 业界动态 > CPU主频比FPGA快,但为啥FPGA才可以加速?

CPU主频比FPGA快,但为啥FPGA才可以加速?

2018-05-21
关键词: CPU FPGA SOC

  CPU的主频高达几个GHz,FPGA的速率往往在几百兆。但是,往往我们会说FPGA会给CPU进行加速。

  虽然CPU主频很高,但其是通用处理器,做某个特定运算(如信号处理,图像处理)可能需要很多个时钟周期;而FPGA可以通过编程重组电路,直接生成专用电路,加上电路并行性,可能做这个特定运算只需要一个时钟周期。

  假设我们用FPGA完整的实现了CPU,然后再跑软件的话,的确比CPU慢。问题是FPGA不会那么干,它会直指问题本质,解决问题。

1.png

  即使我们用FPGA实现一个CPU,也是为了做一些芯片验证或者说需要一些需要CPU和FPGA需要紧密结合的场景,这种场景现在也逐步由SoC的FPGA实现了。

2.png

  举个具体的例子,比如有两个数组,其中有256个32位数,我们现在要把它们对应相加变成一个数组,用CPU写最快大概是这样子的:

  r[0] = a[0] + b[0];

  r[1] = a[1] + b[1];

  ...

  r[255] = a[255] + b[255];

  当然也可能会这么写(在分支预测准确,指令缓存不大的情况下可能更快):

  for (int i = 0; i < 255; i++)

  r[i] = a[i] + b[i];

  CPU指令流水线

  根据之前描述的基础,指令进入流水线,通过流水线处理,从流水线出来的过程,对于我们程序员来说,是比较直观的。

  I486拥有五级流水线。分别是:取指(Fetch),译码(D1, main decode),转址(D2, translate),执行(EX, execute),写回(WB)。某个指令可以在流水线的任何一级。

3.jpg

  流水线的数量不可能无限制增加,流水线的加速也有很多风险。即使流水线可以无限制增加,不管CPU的流水线又多少条,每个指令执行都必须顺序执行。对速率的提升也是有限的。

  对于上图中的流水线有一个明显的缺陷。对于下面的指令代码,它们的功能是将两个变量的内容进行交换。

4.png

  第二条xor指令需要第一条xor指令计算的结果a,但是直到第一条指令执行完成才会写回。所以流水线的其他指令就会在当前流水级等待直到第一条指令的执行和写回阶段完成。第二条指令会等待第一条指令完成才能进入流水线下一级,同样第三条指令也要等待第二条指令完成。

  这个现象被称为流水线阻塞或者流水线气泡。

  对FPGA来说,也可以用上面相同的写法,不同在于:

  CPU是一个一个加法计算,而FPGA排好逻辑电路,在一个时钟周期内计算完毕。就算CPU主频比FPGA快100倍也赶不上啊。

  计算机最基本的功能就是运算了,其中最基本的又要属加法运算。我们知道计算机使用二进制来保存和处理数据,因此这里的加减法运算都是用二进制进行。下面雅乐网总结了一些运算器中加法器的设计。

  二进制加法

1.png

  一位的二进制加法非常简单,因为只有四种情况

  0+0=0 进位0

  0+1=1 进位0

  1+0=1 进位0

  1+1=0 进位1

  多位的二进制加法 和十进制类似,每一位上两个数相加后再加上进位就可以了

  FPGA半加器

  半加器可以实现两个1位的二进制数字相加,并且输出结果和进位。

  真值表:

2.png

  一位半加器真值表

  由表中可以看见,这种加法没有考虑低位来的进位,所以称为半加。

  输出和:A和B一个为0 一个为1的时候输出1  两个0或两个1输出0  因此 可以用异或门连接。

  进位:只有AB均为1的时候进位输出1  进位Cout = AB 用与门连接。

3.png

  一位半加器

  FPGA全加器

  全加器在半加器的基础上 增加了进位 它输入三个数字 两个加数 和 一个进位 Cin,输出结果 和 进位

4.png

  一位全加器真值表

  从真值表很容易写出如下逻辑表达式

  S=P异或Cout      其中P=A异或B

  Cout=P·Cin+G    其中G=A·B

5.png

  一位全加器

  四位行波加法器

  将四个全加器 每一个的仅为输出连接到下一个的进位输入 就可以构成一个4位串行加法器了

6.png

  四位行波加法器

  这样构成的加法器连接起来很简单,但是也有不足:每一个全加器计算的时候必须等待它的进位输入产生后才能计算,所以四个全加器并不是同时进行计算的,而是一个一个的串行计算。这样会造成较大的延迟。

  超前进位加法器(Carry-Lookahead Adder,CLA)

  超前进位加法器的思路是提前算出每一位上的进位。

  分析每一个全加器的局部

  一个全加器 A B Cn 如果有两个或两个以上的1 那么进位Cn+1就是1

  因此 Cn+1 = AB + ACn + BCn = AB + Cn(A+B)

  记生成(Generate)信号:Gi=Ai·Bi

  传播(Propagate)信号:Pi=Ai+Bi

  那么Ci+1=Gi+Pi·Ci

  根据这个递推关系,可以推导出每一位的进位

  每一位的进位跟前一级进位有关,前一级 又跟 前一级的前一级有关 一直向前 最终是和C0相关。而最开始的第一位C0和A0 B0都是已知的

1.jpg

  这样算出结果只需要经过三个门延迟就可以了。

  随着位数的增加,进位的计算公式会越来越复杂。32位的进位计算需要32与门

  所以我们需要更多的计算位宽或者更大的数组,或者矩阵的运算的时候,我们使用FPGA的优势就体现出来。再多的计算,也就是放置更多的逻辑资源。

  FPGA的并行是真并行,CPU完全没得比。CPU如果想并行最多也就是让多个核并行,但是对于大部分算法实现来说,如上例,多个核之间的同步调度开销远远大于计算开销,就算多个核之间的调用开销可以做的很小,一般CPU也就那几个核,而FPGA只要门足够,想并行几路就可以并行几路。

  所以在做可并行的计算密集型任务时,比如信号处理,网络传输等等FPGA可以帮上忙;但是如果做我们常见的串行为主的任务而言,FPGA的确远远比不上CPU。

  FPGA是配角

  使用FPGA不一定总能加速,只是在某些强计算和数据处理的方面,因为其硬件电路并行运行和有很多DSP硬核资源供调用的特点,可以工作得更出色。FPGA本身也只是辅助角色,起控制的还是CPU本身,所以FPGA并不能代替CPU,只是在完成一件大任务的过程中将某部分任务分解给FPGA可以更好地一起完成任务。在这过程中也会有额外的开销产生,在某些场合,可能用了FPGA而效果更差也是有的。

  另外,通常说的使用FPGA加速比CPU和GPU省电,是指在完成同样的任务下,FPGA耗费的电力比起CPU和GPU更少一些,相对而言的,并不是说FPGA本身就一定省电。

  FPGA的弱点

  1.开发周期长。需要对特定的应用编写特定的FPGA。只要干的事情稍有不同,一般来说FPGA代码就要重新写一遍或者是至少要修改很多东西。开发代价和码农码几行代码完全不可比。而且一般需要若干工程师花费若干周才能搞的定。重点是会写的人还不多。

  2.并不是所有东西都适合FPGA。FPGA适合于做那些可并行计算的东西,例如矩阵运算。如果是一些判断类的问题,FPGA算得并没有CPU快(这个时候时钟周期才是关键因素)。所以现实中都是有人来分析,在整个任务中有哪些地方可以并行计算,把这些地方替换为FPGA卡。

  由于现在机器学习、大数据比较火,里面矩阵运算成千上万,所以没有出现定制的ASIC之前,FPGA加速还是业界主流。现在百度、微软、谷歌等公司都已经把FPGA加速运用到了实际的商业运营中。