4. 协同设计架构概览:FPGA+CPU 怎么搭班子
好,咱们进入正题。这一章我打算聊聊 FPGA 和 CPU 到底怎么配合干活。你想想看,一个交易系统里,CPU 负责灵活调度,FPGA 负责硬实时处理,两者各有所长。但怎么把它们捏到一起,就成了门学问。
我在早期做低延迟交易系统时,踩过不少坑。最典型的就是——把不该放 FPGA 的逻辑硬塞进去,结果开发周期翻倍,收益却微乎其微。所以,任务划分才是协同设计的灵魂。
4.1 三种主流协同架构模式
根据我个人的项目经验,FPGA+CPU 的协同架构大致可以归为三类。咱们一个一个说。
4.1.1 加速器模式
这种模式最简单。CPU 还是老大,FPGA 就是个“打手”。CPU 把计算密集的任务卸载给 FPGA,FPGA 算完把结果返回。
举个例子:你在做期权定价,CPU 算一个 Black-Scholes 模型要 10 微秒,FPGA 只要 100 纳秒。那 CPU 就把参数发给 FPGA,等结果回来就行。
特点:
- FPGA 作为协处理器,受 CPU 控制
- 数据流是“请求-响应”模式
- 适合计算密集型、数据量小的任务
我记得有一次,客户要求把行情解码的延迟从 5 微秒降到 500 纳秒。用加速器模式,CPU 只负责管理,FPGA 做 UDP 包解析和行情重组。效果立竿见影。
4.1.2 卸载模式
这种模式更彻底。FPGA 直接接管某些数据通路,CPU 基本不碰这些数据。说白了,就是把 CPU 从繁重的数据搬运中解放出来。
比如网络协议栈。传统做法是 CPU 处理 TCP/IP,但延迟高、吞吐低。用 FPGA 做 TCP 卸载引擎,CPU 只处理应用层逻辑。
我的建议: 如果你发现 CPU 的软中断占用超过 30%,就该考虑卸载模式了。我曾经在一个高频交易项目中,把网卡中断处理从 CPU 卸载到 FPGA,CPU 占用率直接从 80% 降到 15%。
4.1.3 流处理模式
这是我最喜欢的一种模式。数据像流水一样,先经过 FPGA 做预处理,再送到 CPU 做复杂决策。FPGA 和 CPU 之间是流水线关系。
典型的场景:行情数据进来,FPGA 先做校验、解码、归一化,然后通过 DMA 送给 CPU。CPU 做策略计算和订单生成。FPGA 处理第一道,CPU 处理第二道。
注意: 流处理模式对带宽和延迟要求极高。我曾经遇到过 FPGA 处理速度太快,CPU 来不及消费,导致 DMA 缓冲区溢出的问题。解决方案是加反压机制,让 FPGA 等一等 CPU。
4.2 数据平面与控制平面的分离
这个原则,说白了就是“快慢分离”。
数据平面:处理实际业务数据流。要求低延迟、高吞吐、确定性。这部分必须用 FPGA。
控制平面:处理配置、管理、异常。要求灵活、可编程。这部分留给 CPU。
我举个例子你就明白了。一个交易网关:
- 数据平面:FPGA 处理订单的编码、发送、接收、解码。延迟要控制在 100 纳秒以内。
- 控制平面:CPU 处理订单的合法性检查、风控规则、会话管理。这些逻辑经常变,用 FPGA 改起来太慢。
为什么要分离?因为混在一起会出问题。我曾经见过一个团队,把风控逻辑也塞进 FPGA,结果每次改风控规则都要重新综合布线,一搞就是半天。后来改成 CPU 做风控,FPGA 只做数据转发,开发效率提升了好几倍。
4.3 任务划分原则:什么放 FPGA,什么放 CPU?
这是整个协同设计的核心。我总结了一个“三放三不放”原则,你可以参考。
| 放 FPGA | 放 CPU |
|---|---|
| 固定算法、流水线处理 | 复杂决策、分支多 |
| 高吞吐、低延迟要求 | 延迟容忍度高 |
| 数据流简单、无状态 | 有状态、需要大缓存 |
| 位操作、协议解析 | 浮点运算、复杂数学 |
| 确定性延迟 | 非确定性、异常处理 |
核心判断标准: 如果一个任务,用 FPGA 实现后延迟能降低 10 倍以上,且逻辑不会频繁变更,那就放 FPGA。否则,老老实实用 CPU。
我个人的经验是:数据搬运和简单计算放 FPGA,复杂决策和配置管理放 CPU。别想着用 FPGA 实现一个完整的交易策略,那会把自己逼疯的。
4.4 架构图:FPGA+CPU 协同数据流
下面这张图,是我根据一个实际项目画的。它展示了典型的流处理模式下,数据平面和控制平面如何协同工作。
这张图里,数据从网络进来,先经过 FPGA 数据平面做预处理,然后送给 CPU 做策略计算。控制平面负责配置和监控,确保整个系统稳定运行。虚线是控制流,实线是数据流。两者互不干扰。
4.5 避坑指南
最后,分享几个我踩过的坑,希望能帮你少走弯路。
坑一: 我曾经把一个复杂的排序算法放到 FPGA 里实现,结果开发了两个月,延迟只比 CPU 快 20%。后来发现,排序算法在 FPGA 里并不占优势,因为它的分支太多,流水线很难做。正确的做法是:用 FPGA 做数据过滤,CPU 做排序。
坑二: 数据平面和控制平面共用同一个 PCIe 通道。结果控制平面的配置操作阻塞了数据流,导致丢包。后来我强制把控制平面走独立的低速通道,问题解决。
我的习惯: 每次设计协同架构时,我会先画一张数据流图,标出每个节点的延迟要求。然后问自己三个问题:这个任务能流水线化吗?它的逻辑会频繁变更吗?用 FPGA 实现后延迟能降低多少?如果三个答案都是肯定的,那就放 FPGA。
好了,这一章的内容就到这里。记住,协同设计的核心不是技术,而是取舍。知道什么该放 FPGA,什么该放 CPU,比你会写多少行 Verilog 代码更重要。