高性能浮点处理一直与高性能 CPU 相关联。在过去几年中,GPU 也成为功能强大的浮点处理平台,超越了图形,称为 GP-GPU(通用图形处理单元)。新创新是在苛刻的应用中实现基于 FPGA 的浮点处理。本文的重点是 FPGA 及其浮点性能和设计流程,以及 OpenCL 的使用,这是高性能浮点计算前沿的编程语言。 

  

各种处理平台的 GFLOP 指标在不断提高,现在,TFLOP/s 这一术语已经使用的非常广泛了。但是,在某些平台上,峰值 GFLOP/s,即,TFLOP/s 表示的器件性能信息有限。它只表示了每秒能够完成的理论浮点加法或者乘法总数。分析表明,FPGA 单精度浮点处理能够超过 1 TFLOP/s。 

  

一种不太复杂的常用算法是 FFT。使用单精度浮点实现了 4096 点 FFT。它能够在每个时钟周期输入输出四个复数采样。每一个 FFT 内核运行速度超过 80 GFLOP/s,大容量 FPGA 的资源支持实现 7 个这类的内核。 

  

但是,如图 1 所示,这一 FPGA 的 FFT 算法 GFLOP/s 接近 400 GFLOP/s。这是“按键式”OpenCL 编译结果,不需要 FPGA 专业知识。使用逻辑锁定和 DSE 进行优化,7 内核设计接近单内核设计的 Fmax,将其 GFLOP/s 提升至 500,超过了 10 GFLOP/s 每瓦。 

  

这一每瓦 GFLOP/s 要比 CPU 或者 GPU 功效高很多。对比一下 GPU,GPU 在这些 FFT 长度上效率并不高,因此,没有进行基准测试。当 FFT 长度达到几十万个点时,GPU 效率才比较高,能够为 CPU 提供有效的加速功能。 

 

 

图 1:Altera Stratix V 5SGSD8 FPGA 浮点 FFT 性能。 

  

总之,实际的 GFLOP/s 一般只达到峰值或者理论 GFLOP/s 的一小部分。出于这一原因,更好的方法是采用算法来对比性能,这种算法能够合理的表示典型应用的特性。算法越复杂,典型实际应用的基准测试就越具有代表性。 

  

并不是依靠供应商的峰值 GFLOP/s 指标来确定处理技术,而是使用比较复杂具有代表性的第三方评估。高性能计算理想的算法是 Cholesky 分解。 

  

这一算法经常用于线性代数,高效的解出多个方程,可以实现矩阵求逆功能。这一算法非常复杂,要获得合理的结果总是要求浮点数值表示。计算需求与 N3 成正比,N 是矩阵维度,因此,一般对处理要求很高。实际 GFLOP/s 取决于矩阵大小以及所要求的矩阵处理吞吐量。 

  

表 1 显示了基于 Nvidia GPU 指标 1.35TFLOP/s 的基准测试结果,使用了各种库,以及 Xilinx Virtex6 XC6VSX475T,其密度达到 475K LC,这种 FPGA 针对 DSP 处理进行了优化。用于 Cholesky 基准测试时,这些器件在密度上与 Altera FPGA 相似。 

 

 

表 1:田纳西州大学的 GPU 和 Xilinx FPGA Cholesky 基准测试。 

  

LAPACK 和 MAGMA 是商用库,而 GPU GFLOP/s 是指采用田纳西州大学开发的 OpenCL 实现的。对于小规模矩阵,后者更优化一些。 

  

中等规模的 Altera Stratix V FPGA (460kLE)也进行了基准测试,使用了单精度浮点 Cholesky 算法。如表 2 所示,在 Stratix V FPGA 上进行 Cholesky 算法的性能要比 Xilinx 结果高很多。 

 

 

表 2:BDTI 的 Altera FPGA Cholesky 和 QR 基准测试。 

  

应指出,矩阵大小并不相同。田纳西州大学结果是从[512×512]矩阵大小开始的。BDTI 基准测试达到了[360×360]矩阵大小。原因是,矩阵规模较小时,GPU 效率非常低,因此,在这些应用中,不应该使用它们来加速 CPU。在规模较小的矩阵时,FPGA 的工作效率非常高。 

  

其次,BDTI 基准测试是基于每个 Cholesky 内核的。每个可参数赋值的 Cholesky 内核支持选择矩阵大小,矢量大小和通道数量。矢量大小大致决定了 FPGA 资源。较大的[360×360]矩阵使用了较长的矢量,支持这一 FPGA 中实现一个内核,达到 91GFLOP/s。较小的[60×60]矩阵使用的资源更少,因此,可以实现两个内核,总共是 2×39=78GFLOP/s。最小的[30×30]矩阵支持实现三个内核,总共是 3×26=78GFLOP/s。 

  

FPGA 看起来更适合解决数据规模较小的问题。原因之一是因为计算负载随 N3 而增大,数据 I/O 随 N2 增大,最终,随着数据的增加,GPU 的 I/O 瓶颈不再是问题。另一项考虑是吞吐量。随着矩阵规模的增大,由于每个矩阵的处理量增大,矩阵每秒吞吐量会大幅度下降。在某些点,吞吐量变得非常低,以至于无法满足很多应用的要求。在很多情况下,会分解大规模矩阵,处理每个小的子矩阵,以解决由于庞大的处理负载造成的吞吐量限制问题。 

  

对于 FFT,计算负载增加 N log2 N,而数据 I/O 随 N 增大而增大。对于规模较大的数据,GPU 是高效的计算引擎。作为对比,数据长度很短时,FPGA 是高效的计算引擎,更适合 FFT 长度达到数千的很多应用,对于 GPU,FFT 长度是数十万。 

 

GPU 和 FPGA 设计方法 

使用 Nvidia 的专用 CUDA 语言或者开放标准 OpenCL 语言对 GPU 进行编程。这些语言在能力上非常相似,而最大的不同在于 CUDA 只能用在 Nvidia GPU 上。 

  

FPGA 通常使用 HDL 语言 Verilog 或者 VHDL 进行编程。这些语言的最新版虽然采用了浮点数定义,不用进行综合,但都不太适合支持浮点设计。例如,在 System Verilog 中,短实数变量与 IEEE 单精度(浮点)对应,实数变量与 IEEE 双精度对应。 

  

使用传统的方法,将浮点数据通路综合到 FPGA 的效率非常低。Xilinx FPGA 在 Cholesky 算法上的性能很低,它使用了 Xilinx 浮点内核生成功能,这证实了这一点。而 Altera 采用了两种不同的方法。第一种使用基于 Mathworks 的设计输入,称之为 DSP Builder 高级模块库。这一工具包含了对定点和浮点数的支持。它支持 7 种不同精度的浮点,包括 IEEE 半精度、单精度和双精度。它还支持矢量化,这是高效实现线性代数所需要的。而最重要的是,它能够将浮点电路高效的映射到目前的定点 FPGA 体系结构中,如基准测试所示,规模中等的 28 nm FPGA,Cholesky 算法接近了 100GFLOP/s。作为对比,在不具有综合能力的规模相似的 Xilinx FPGA 上,实现同样的算法,使用密度相似的 FPGA,性能只有 20GFLOP/s。 

  

GPU 编程人员比较熟悉 OpenCL。面向 FPGA 的 OpenCL 编译意味着,面向 AMD 或者 Nvidia GPU 编写的 OpenCL 代码可以编译到 FPGA 中。Altera 的 OpenCL 编译器支持 GPU 程序使用 FPGA,不需要熟练的开发典型的 FPGA 设计。 

  

使用支持 FPGA 的 OpenCL,相对于 GPU 有几个关键优势。首先,GPU 的 I/O 是有限制的。所有输入和输出数据必须由主 CPU 通过 PCI 接口进行传输。结果延时会让 GPU 处理引擎暂停,因此,降低了性能。 

  

FPGA 以各种宽带 I/O 功能而知名。这些功能支持数据通过千兆以太网和 SRIO,或者直接从 ADC 和 DAC 输入输出 FPGA。Altera 定义了 OpenCL 标准的供应商专用扩展,以支持流操作。 

  

即使与 I/O 瓶颈无关,FPGA 的处理延时也要比 GPU 低很多。众所周知,GPU 必须有数千个线程才能高效的工作。这是由于存储器读取很长的延时,以及 GPU 大量的处理内核之间的延时。实际上,GPU 必须有很多任务才能使得处理内核不会暂停等待数据,否则会导致任务很长的延时。 

  

而 FPGA 使用了“粗粒度并行”体系结构。它建立了多个经过优化的并行数据通路,每一通路一般在每个时钟周期输出一个结果。数据通路的例化数取决于 FPGA 资源,但一般要比 GPU 内核数少很多。但是,每一数据通路例化的吞吐量要比 GPU 内核高得多。这一方法的主要优势是低延时。降低延时在很多应用中都是关键的性能优势。 

  

FPGA 的另一优势是很低的功耗,极大的降低了每瓦 GFLOP/s。正如 BDTI 所测量的,Cholesky 等复数浮点算法的每瓦 GFLOP/s 是每瓦 5~6GFLOP/s。一般很难进行 GPU 能效测量,但是,Cholesky 的 GPU 性能达到 50GFLOP/s,典型功耗是 200W,得到的结果是 0.25 每瓦 GFLOP/s,单位 FLOP/s 的功率高 20 倍。 

  

OpenCL 和 DSP Builder 都依靠“融合数据通路”这种技术(图 2),以这种技术实现浮点处理,能够大幅度减少桶形移位电路,从而支持使用 FPGA 来开发大规模高性能浮点设计。 

 

 

图 2:浮点的融合数据通路实现。 

  

为降低桶形移位频率,综合过程尽可能使用较大的尾数宽度,从而不需要频率归一化和去归一化。27×27 和 36×36 硬核乘法器支持比单精度实现所要求的 23 位更大的乘法计算,54×54 和 72×72 结构的乘法器支持比 52 位更大的计算,这通常是双精度实现所要求的。FPGA 逻辑已经针对大规模定点加法器电路进行了优化,包括了内置进位超前电路。 

  

当需要进行归一化和去归一化时,另一种可以避免低性能和过度布线的方法是使用乘法器。对于一个 24 位单精度尾数(包括符号位),24×24 乘法器通过乘以 2n 对输入移位。27×27 和 36×36 硬核乘法器支持单精度扩展尾数,可以用于构建双精度乘法器。 

  

在很多线性代数算法中,矢量点乘(图 3)是占用大量 FLOP/s 的底层运算。单精度实现长度是 64 的长矢量点乘需要 64 个浮点乘法器,以及随后由 63 个浮点加法器构成的加法树。这类实现需要很多桶形移位电路。 

 

 

图 3:矢量点乘优化。 

  

相反,可以对 64 个乘法器的输出进行去归一化,成为公共指数,最大是 64 位指数。可以使用定点加法器电路对这些 64 路输出求和,在加法树的最后进行最终的归一化。如图 3 所示,这一本地模块浮点处理过程省掉了每一加法器所需要的临时归一化和去归一化。即使是 IEEE754 浮点,最大指数基本决定了最终的指数,因此,这种改变只是在计算早期进行指数调整。 

  

但是,进行信号处理时,在计算最后尽可能以高精度来截断结果才能获得最佳结果。这种方法进位额外的尾数,补偿了单精度浮点处理所需要的早期去归一化次优方法,一般从 27 位到 36 位。采用浮点乘法器进行尾数扩展,因此,在每一步不需要对乘积进行归一化。 

  

注意,这一方法每个时钟周期也会产生一个结果。GPU 体系结构可以并行产生所有浮点乘法,但是不能高效的并行进行加法。之所以这样是因为不同的内核必须通过本地存储器传输数据,彼此实现通信,因此,不能灵活的连接 FPGA 体系结构。 

  

这一方法产生的结果要比传统 IEEE754 浮点结果精确得多,如表 3 的测量结果所示。BDTI 的基准测试获得了相似的结果。 

 

 

表 3:FPGA 相对于 IEEE754 浮点更精确的结果。 

  

使用 Cholesky 分解算法,实现大规模矩阵求逆,获得了表 3 的结果。以三种不同的方法实现了相同的算法——在 Matlab/Simulink 中,使用了 IEEE754 单精度浮点,在 RTL 单精度浮点处理中,使用融合数据通路方法,在 Matlab 中也使用了双精度浮点。双精度实现要比单精度实现精度高十亿倍(109)。 

  

表 3 对比了 Matlab 单精度;RTL 单精度和 Matlab 双精度存在误差,确认了融合数据通路方法的完整性。采用了这一方法来获得输出矩阵中所有复数元素的归一化误差以及矩阵元素的最大误差。使用 Frobenius 范数计算了总误差和范数: 


  

 

请注意,由于范数包括了所有元素的误差,因此,它要比每一误差大很多。 

  

而且,DSP Builder 高级模块库和 OpenCL 工具流程都针对下一代 FPGA 体系结构,支持并优化目前的设计。由于体系结构创新和工艺技术创新,性能可以达到 100 峰值 GFLOPs/W。 

  

总结 

高性能计算应用现在有新的处理平台选择。对于特殊类型的浮点算法,FPGA 能够提供低延时和较高的 GFLOP/s。在几乎所有应用中,FPGA 都能够实现优异的每瓦 GFLOP/s。随着下一代高性能计算优化 FPGA 的推出,这种优势会更明显。 

  

Altera 的 OpenCL 编译器为 GPU 编程人员提供了几乎无缝的方法来评估这一新处理体系结构的指标。Altera OpenCL 符合 1.2 规范,提供全面的数据库支持。它解决了传统 FPGA 遇到的时序收敛、DDR 存储器管理以及 PCIe 主处理器接口等难题。 

 

对于非 GPU 开发人员,Altera 提供 DSP Builder 高级模块库工具流程,支持开发人员开发高 Fmax 定点或者浮点 DSP 设计,同时保持了基于 Mathworks 的仿真和开发环境的优点。要求高效能工作流程的 FPGA 开发人员多年以来一直使用这一产品,与经验丰富的 FPGA 开发人员相比,所实现的 Fmax 性能相同。