FPGA 如何胜过 CPU?

电器工程 FPGA 中央处理器
2022-01-13 01:31:24

我听说有人使用 FPGA 来提高系统的性能,比如比特币挖掘、电子交易和蛋白质折叠。

当 CPU 通常运行速度至少快一个数量级(就时钟速度而言)时,FPGA 如何在性能上与 CPU 竞争?

4个回答

CPU 是顺序处理设备。他们将算法分解为一系列操作并一次执行一个。

FPGA 是(或可配置为)并行处理设备。整个算法可能在单个时钟滴答中执行,或者,最坏的情况下,时钟滴答可能比顺序处理器所需的时钟滴答少得多。增加的逻辑复杂性的成本之一通常是可以为设备提供时钟的下限。

考虑到上述情况,FPGA 在执行某些任务时可以胜过 CPU,因为它们可以在更少的时钟周期内完成相同的任务,尽管整体时钟速率较低。可以实现的增益高度依赖于算法,但至少一个数量级对于 FFT 之类的东西来说并不是非典型的。

此外,由于您可以在 FPGA 中构建多个并行执行单元,如果您有大量数据要通过相同的算法,您可以将数据分布在并行执行单元之间,从而获得更高数量级的吞吐量即使是多核 CPU 也无法实现。

您为这些优势付出的代价是功耗和美元。

Markt 基本上是正确的,但我要在这里投入 2 美分:

想象一下,我告诉过你我想编写一个程序来反转 32 位整数中的位顺序。像这样的东西:

int reverseBits(int input) {
    output = 0;
    for(int i = 0;i < 32;i++) {
        // Check if the lowest bit is set
        if(input & 1 != 0) {
            output = output | 1; // set the lowest bit to match in the output!
        }

        input = input >> 1;
        output = output << 1;
    }
    return output;
}

现在我的实现并不优雅,但我相信你同意这样做会涉及一些操作,并且可能是某种循环。这意味着在 CPU 中,您已经花费了超过 1 个周期来执行此操作。

在 FPGA 中,您可以简单地将其连接为一对锁存器。您将数据放入某个寄存器,然后以相反的位顺序将其连接到不同的寄存器。这意味着该操作将在 FPGA 中的单个时钟周期内完成。因此,在一个周期内,FPGS 完成了一个需要您的通用 CPU 数千个周期才能完成的操作!此外,您可以并行连接大约数百个这样的寄存器。因此,如果您可以将几百个数字移动到 FPGA 上,它会在一个周期内完成数千次操作,全部在 1 个 FPGA 时钟周期内完成。

通用 CPU 可以做很多事情,但作为限制,我们设置了通用且简单的指令,这些指令必须扩展为简单指令列表才能完成某些任务。所以我可以让通用 CPU 有一个类似“32 位寄存器的反转位顺序”的指令,并赋予 CPU 与我们刚刚构建的 FPGA 相同的功能,但是这样可能的有用指令的数量是无限的,所以我们只放入那些保证流行 CPU 成本的产品。

FPGA、CPLD 和 ASIC 都可以让您访问原始硬件,从而允许您定义疯狂的操作,例如“使用密钥解密 AES256 加密字节”或“解码 h.264 视频帧”。这些在 FPGA 中具有超过一个时钟周期的延迟,但它们可以以比在数百万行通用汇编代码中写出操作更有效的方式实现。这还具有使用于许多这些操作的固定用途 FPGA/ASIC 更节能的好处,因为它们不必做太多无关的工作!

并行性是 markt 指出的另一部分,虽然这也很重要,但主要是当 FPGA 并行化某些在 CPU 中已经很昂贵的东西时,就执行操作所需的周期而言。一旦你开始说“我可以在 10 个 FPGA 周期内执行一项需要占用我的 CPU 100,000 个周期的任务,并且我可以一次并行执行 4 个项目”,你就会很容易理解为什么 FPGA 可以这么多比CPU还快!

那么为什么我们不使用 FPGA、CPLD 和 ASIC 呢?因为通常它是一个只做一个操作的完整芯片。这意味着尽管您可以让一个进程在您的 FPGA/ASIC 中运行速度提高许多数量级,但是当该操作不再有用时,您无法在以后更改它。FPGA一旦进入电路就不能(通常)更改它的原因是接口的接线是固定的,通常电路不包含允许您将FPGA重新编程为更有用的配置的组件。有一些研究人员试图构建混合 FPGA-CPU 模块,其中有一部分 CPU 能够像 FPGA 一样重新布线/重新编程,允许您“加载”CPU 的有效部分,

这里提供的所有其他流行答案都谈到了 FPGA 和 CPU 之间的字面差异。他们指出了 FPGA 的并行特性与 CPU 的顺序特性,或者举例说明了为什么某些算法可能在 FPGA 上运行良好。所有这些都是好的和真实的,但我建议 CPU 和 FPGA 之间存在更根本的区别。

FPGA和CPU之间的共同点是什么?这是因为它们都建立在硅之上。在某些情况下,实际上是相同的硅工艺。

根本区别在于我们堆积在硅片之上的抽象。一个人不可能理解单个现代 CPU 设计从硅到封装 IC 的全部细节。因此,作为工程过程的一部分,我们将这个复杂的问题划分为更小的可管理问题,人类可以解决这些问题。

考虑一下将硅片变成功能正常的 CPU 需要什么。这是实现该目标所需的抽象层的简化视图:

  1. 首先,我们有知道如何用硅制造晶体管的工程师。他们知道如何设计能够以 10 甚至 100 千兆赫兹的速率吸收功率和开关的微型晶体管,并且他们知道如何设计强大的晶体管,这些晶体管能够以足够的功率驱动信号以将信号从 IC 封装中发送出去并穿过 PCB到另一个芯片。

  2. 然后我们有数字逻辑设计人员,他们知道如何将这些晶体管组合到具有数百个不同逻辑单元的库中。逻辑门、触发器、多路复用器和加法器等等。都有各种配置。

  3. 接下来,我们有不同的工程师小组,他们知道如何将这些数字(有时是模拟)模块组合在一起以形成更高级别的功能模块,如高速收发器、内存控制器、分支预测器、ALU 等。

  4. 然后我们让 CPU 设计人员通过将这些功能单元组合成一个完整的系统来构建高端 CPU 设计。

它并不止于此。在这一点上,我们有一个运行汇编代码的工作 CPU,但这不是当今大多数程序员编写的语言。

  1. 我们可能有一个 C 编译器来编译成汇编代码(可能通过一些中间表示)
  2. 我们可以在 C 之上添加另一个抽象来获得面向对象的语言
  3. 我们甚至可以在 C 或 C++ 之上编写一个虚拟机,以便我们可以解释诸如 Java 字节码之类的东西

抽象层可以从那里继续。这里重要的一点是,这些抽象层结合起来产生了一个基于 CPU 的系统,该系统可以大规模扩展并且成本只是定制硅设计的一小部分。

然而,这里要强调的重要一点是,每个抽象本身也有成本。晶体管设计者不会为每个用例构建完美的晶体管。他建立了一个合理的库,因此有时使用的晶体管消耗的功率或硅片比手头工作的实际需要多一点。同样,逻辑设计者也不会构建每一个可能的逻辑单元。他们可能会构建一个 4 输入 NAND 门和一个 8 输入 NAND 门,但是当另一个工程师需要一个 6 输入 NAND 时会发生什么?他使用了一个 8 输入与非门并连接了 2 个未使用的输入,这导致了硅资源的损失和功耗的降低。所以它沿着抽象链上升。每一层都为我们提供了一种处理复杂性的方法,

现在将这些抽象与 FPGA 所需的抽象进行比较。本质上,FPGA 抽象在上面列表中的 #2 处停止。FPGA 允许开发人员在数字逻辑层工作。它比这更复杂一些,因为 CPU 在这一层是“硬编码”的,并且 FPGA 必须在运行时进行配置(顺便说一句,这就是 CPU 通常运行更高频率的原因),但重要的事实是,这还远远不够FPGA 的抽象比 CPU 少。

那么,为什么 FPGA 可以比 CPU 更快呢? 从本质上讲,这是因为 FPGA 使用的抽象比 CPU 少得多,这意味着设计人员的工作更接近芯片。他没有支付 CPU 所需的所有许多抽象层的成本。他的代码水平较低,必须更加努力地工作才能实现给定的功能,但他得到的回报却是更高的性能。

但当然,减少抽象也有不利的一面。所有这些 CPU 抽象都是有充分理由的。它们为我们提供了一个更简单的编码范例,这意味着更多的人可以轻松地为它们开发。这反过来意味着存在更多的 CPU 设计,因此我们可以从 CPU 中获得巨大的价格/规模/上市时间优势。

所以你有它。FPGA 的抽象较少,因此它们可以更快、更节能,但难以编程。CPU 有许多抽象设计,使它们易于开发、可扩展且便宜。但他们为了这些利益而放弃了贸易的速度和力量。

虽然其他答案都是正确的,但它们都没有解决您问题中的比特币挖掘示例,这确实是一个不错的示例。比特币挖掘涉及重复计算加密哈希函数,即另一个 SHA-256 计算结果的 SHA-256,数据只有一个 32 位整数发生变化,直到生成的哈希具有某些属性。每个 SHA-256 包含 64 次相同算法的重复,包括 32 位加法、位移和一些更多的位处理操作。

如果您在 32 位(或更多)CPU 上编写此循环,您会发现它的指令集非常适合该任务——SHA-256 旨在在 CPU 上高效运行。您仍然只能使用现代 CPU 硅面积的 2%,具有区域密集型功能,如缓存、乘法、除法、浮点运算、分支和分支预测等,要么根本不使用,要么无法提供显着的功能此特定任务的性能提升。

在像 FPGA 这样的可配置硬件中,您只需实现这 2%,并通过忘记所有代码执行来进一步优化,而不是设计门来直接计算那些经常重复的子功能中的每一个。流水线化,使得每个时钟周期都将结果传递到下一个时钟周期,并重复 128 次(以及每个 SHA-256 开始和结束的一些特殊附加逻辑),最终每个时钟周期都会得到一个结果(可能在比这更简单的逻辑上支持 300 MHz 的 FPGA 上每秒 1 亿次哈希)而在现代 CPU 上,您可以期望每个内核每几千个时钟周期一个结果,例如在多核多核上每秒 1000 万次哈希-GHz CPU。

如果您对这个特定示例感兴趣,您可能想查看我在 bitcoin.stackexchange 上关于 ASIC 矿工内部的相关回答,因为许多 FPGA 矿工使用可配置而非定制硬件以相同的方式工作。只是为了完整起见:还有其他可能性,比如限制或避免我描述的流水线,通过使用多个独立的 SHA-256 哈希器来支持更简单的并行化。根据 FPGA 内部结构及其总尺寸的限制,它甚至可以提供更好的性能,尽管如果您在设计整个芯片时拥有完全的自由度,而不仅仅是 FPGA 的配置,那么它在门数和布线开销方面的效率会更低.