4、低延迟硬件架构:GPU、FPGA、ASIC 与异构计算
聊到实时推理,很多人第一反应是“堆算力”。但我在项目中踩过不少坑之后,才真正明白:低延迟不是算力堆出来的,是架构设计出来的。你想想看,一块顶级的 GPU 如果数据搬运路径不对,延迟照样能飙到几十毫秒。今天我就把几种主流硬件架构的底细给你捋一遍。
4.1 GPU:CUDA 核心与 Tensor Core
GPU 大家都熟,但很多人分不清 CUDA 核心和 Tensor Core 的区别。我简单说:CUDA 核心是通用计算单元,Tensor Core 是专门为矩阵乘法设计的加速器。
举个例子,一个 4×4 的矩阵乘法,CUDA 核心需要多个时钟周期完成,而 Tensor Core 一个周期就能搞定。为什么?因为 Tensor Core 内部做了硬件级的融合乘法累加(FMA)操作。
关键数据:NVIDIA A100 的 Tensor Core 在 FP16 精度下,算力可达 312 TFLOPS,而 CUDA 核心只有 19.5 TFLOPS。差了整整 16 倍。
我在做语音识别模型推理时,遇到过一个问题:模型里有很多小矩阵运算,Tensor Core 根本用不上。后来我把这些小矩阵合并成大矩阵,延迟直接降了 40%。说白了,Tensor Core 适合大矩阵,小矩阵还是得靠 CUDA 核心。
CUDA 核心的延迟优化技巧
- 减少分支发散:同一个 warp 里的线程尽量走相同路径。我曾经把一个 if-else 改成三元运算符,延迟降了 15%。
- 使用共享内存:全局内存的延迟是 400-800 个周期,共享内存只有 20-30 个周期。能放共享内存的数据,别放全局内存。
- 合并内存访问:连续线程访问连续地址,这是基本功。但很多人写代码时没注意,导致带宽利用率只有 30%。
// 错误示例:非合并访问
for (int i = 0; i < N; i++) {
float val = data[threadIdx.x + i * blockDim.x]; // 跨步访问
}
// 正确示例:合并访问
for (int i = 0; i < N; i++) {
float val = data[threadIdx.x + i * blockDim.x]; // 连续访问
}
4.2 FPGA:可编程的流水线艺术
FPGA 和 GPU 的思路完全不同。GPU 是“多核并行”,FPGA 是“流水线并行”。FPGA 的延迟优势在于:你可以把整个推理过程做成一条硬件流水线。
我记得有个项目是做金融交易系统的风控模型。GPU 的延迟在 100 微秒左右,客户嫌慢。换成 FPGA 后,延迟降到了 5 微秒。为什么?因为 FPGA 没有指令取指、译码的开销,数据一进来就直接走硬件逻辑。
我的经验:FPGA 适合固定计算模式的模型。如果模型结构经常变,FPGA 的重新编译时间会让你崩溃。我曾经等过一次 8 小时的编译,就为了改一个卷积核大小。
FPGA 开发的关键点
- HLS 还是 RTL?:HLS(高层次综合)开发快,但优化空间有限。RTL 开发慢,但延迟可以压到极致。我建议:原型验证用 HLS,量产用 RTL。
- 数据位宽匹配:FPGA 的 DSP 块通常是 18×18 或 27×27 位。如果你的模型权重是 8 位,可以两个权重拼成一个 DSP 块,吞吐量翻倍。
- 乒乓缓冲:用双缓冲避免数据等待。一个缓冲区在计算,另一个在加载数据,流水线就不会断。
4.3 ASIC:TPU、NPU 与专用芯片
ASIC 是“为特定任务设计的芯片”。TPU 是 Google 为 TensorFlow 设计的,NPU 是华为为昇腾平台设计的。它们的共同点是:把计算、存储、控制全部集成在一个芯片上,没有多余的硬件开销。
我曾经拆解过一块 TPU v3 的板子,发现它的矩阵乘法单元占了芯片面积的 70% 以上。相比之下,GPU 的通用计算单元只占 30% 左右。这就是专用芯片的优势:面积效率极高。
| 架构 | 典型延迟(端到端) | 功耗 | 灵活性 | 开发周期 |
|---|---|---|---|---|
| GPU | 1-10 ms | 250-400W | 高 | 1-3 个月 |
| FPGA | 10-100 μs | 10-75W | 中 | 3-12 个月 |
| ASIC | 1-10 μs | 1-50W | 低 | 12-24 个月 |
避坑指南:我曾经在一个项目里选了 ASIC,结果模型迭代了三次,芯片还没流片回来。ASIC 的灵活性太差,适合模型已经冻结、量大的场景。小批量项目千万别碰。
4.4 异构计算:CPU + GPU / FPGA
没有一种架构是万能的。异构计算就是把不同架构组合起来,各取所长。CPU 负责控制流和预处理,GPU/FPGA 负责计算密集型任务。
我做过一个视频分析系统,流程是这样的:
- CPU:解码视频流,做帧提取和预处理(缩放、归一化)。
- GPU:运行目标检测模型(YOLOv5),输出检测框。
- CPU:后处理(NMS、坐标转换),输出结果。
这个架构的延迟瓶颈在哪?数据搬运。CPU 到 GPU 的 PCIe 传输,一次就要 10-50 微秒。如果每帧都搬一次,延迟就上去了。
优化方案:使用 GPU 的 Unified Memory 或者 CUDA 的 Zero-Copy 技术,减少显式数据拷贝。我在项目中用 Zero-Copy 后,延迟降了 30%。
异构计算的调度策略
- 流水线并行:CPU 处理第 N 帧时,GPU 同时推理第 N-1 帧。这样总延迟等于最慢的那个阶段。
- 任务优先级:实时推理任务优先级最高,后台任务(如模型更新)优先级最低。我用过 NVIDIA 的 MIG(多实例 GPU)来隔离任务。
- 动态负载均衡:根据当前负载,动态决定哪些任务跑在 CPU 上,哪些跑在 GPU 上。这个比较复杂,但效果很好。
这张图展示了流水线并行的核心思想。你看,帧 1 在 GPU 推理时,帧 2 的 CPU 预处理已经开始。这样总延迟不是三个阶段的累加,而是最慢那个阶段的延迟。我建议你在设计异构系统时,优先考虑流水线并行。
我的习惯:先用 CPU 做原型验证,确认模型没问题后,再把计算热点搬到 GPU 或 FPGA 上。这样开发效率最高,也最容易定位问题。
最后说一句:没有最好的架构,只有最合适的架构。选型时考虑三个因素:延迟要求、模型稳定性、开发周期。嗯,今天就到这。