2. 硬件瓶颈分析

硬件瓶颈,说白了就是你的系统里最慢的那个环节。人脸识别系统跑得慢,很多时候不是算法不行,而是硬件没喂饱。我见过太多团队,花几个月调模型精度,结果一上线发现 GPU 利用率才 30%,数据全堵在 PCIe 总线上。嗯,这章我们就来拆开看看,到底该怎么定位这些硬件层面的坑。

2.1 计算单元:CPU / GPU / TPU 的能力评估

先看计算单元。人脸识别流水线里,CPU、GPU、TPU 各管一摊。你得知道它们各自擅长什么,才能对症下药。

2.1.1 CPU:控制流与预处理的主战场

CPU 负责图像解码、人脸检测的前处理、以及一些轻量级逻辑判断。我个人习惯用 perf stat 和 top 先扫一眼 CPU 的利用率。

关键指标

  • CPU 利用率:如果持续 > 90%,说明 CPU 是瓶颈。
  • 上下文切换:每秒超过 10 万次,说明线程调度开销过大。
  • IPC(每时钟周期指令数):低于 0.5 说明缓存命中率低或分支预测失败率高。

我在项目中遇到过一个问题:单路服务器跑人脸检测,CPU 利用率 100%,但 GPU 闲着。后来发现是图像解码用了软解,没走硬件加速。换成 libyuv 配合 GPU 的 NVDEC,CPU 利用率直接降到 20%。

避坑指南

我曾经在调优时忽略了 NUMA 架构。CPU 跨 socket 访问内存,延迟能差 2-3 倍。用 numactl --hardware 看一下,把进程绑定到同一个 NUMA 节点上,效果立竿见影。

2.1.2 GPU:并行计算的引擎

GPU 是深度学习推理的主力。评估 GPU 瓶颈,我主要看三个维度:

指标 正常范围 瓶颈信号
GPU 利用率 80% - 95% < 50% 说明数据供给不足
显存占用 不超过 80% > 95% 可能触发 OOM 或 swap
PCIe 带宽利用率 < 30% > 60% 说明数据传输成为瓶颈

用 nvidia-smi dmon -s pucvmet -d 1 可以实时看这些数据。你想想看,如果 GPU 利用率只有 30%,但显存快满了,那多半是模型太大,或者 batch size 设置不合理。

注意

别只看 GPU 利用率。我见过有人把 batch size 设得特别大,GPU 利用率 95%,但单张图片的延迟反而高了。因为显存带宽被占满,计算单元在等数据。这时候要调小 batch size,或者用混合精度训练/推理。

2.1.3 TPU:专用芯片的取舍

TPU 是 Google 的专用芯片,适合大规模 batch 推理。但说实话,在人脸识别场景里,TPU 的灵活性不如 GPU。它的矩阵乘法单元很强,但控制逻辑弱,不适合做复杂的预处理。

我建议只有在以下情况才考虑 TPU:

  • 模型已经固定,不需要频繁迭代
  • batch size 很大(比如 128 以上)
  • 对功耗有严格要求

否则,GPU 的生态和工具链更成熟,调试起来也方便。

2.2 内存带宽与延迟:被忽视的隐形瓶颈

内存瓶颈是最容易被忽视的。很多人盯着计算单元,却忘了数据在内存里堵车。为什么会这样?因为 CPU 和 GPU 的计算速度增长远快于内存带宽的增长。

2.2.1 内存带宽评估

用 stream 基准测试可以测内存带宽。我习惯跑一次 stream_c.exe,看看实际带宽和理论带宽的差距。

# 安装 stream 并运行
wget https://www.cs.virginia.edu/stream/FTP/Code/stream.c
gcc -O3 -march=native -mtune=native -DSTREAM_ARRAY_SIZE=100000000 -DNTIMES=20 stream.c -o stream
./stream

如果实测带宽只有理论值的 60% 以下,说明内存子系统有问题。可能的原因:

  • 内存插槽没插满,没跑在双通道/四通道模式
  • 内存频率被 BIOS 降频了
  • NUMA 节点间跨访存

实战案例

有一次,一个客户的人脸识别系统延迟总是波动很大。我查了 CPU 和 GPU 都没问题,最后用 perf stat -e cache-misses 一看,L3 缓存缺失率高达 40%。原因是他们用了虚拟化,宿主机把 vCPU 的缓存亲和性打乱了。改成 pin vCPU 到物理核后,延迟稳定了。

2.2.2 内存延迟的影响

内存延迟对实时人脸识别影响很大。尤其是人脸检测阶段,需要频繁访问特征图数据。如果延迟高,GPU 的 warp 就会空转。

我建议用 mlc(Intel Memory Latency Checker)来测延迟:

./mlc --latency_matrix

输出会显示不同 NUMA 节点间的延迟。如果跨节点延迟超过 150ns,就要考虑调整内存分配策略了。

2.3 I/O 瓶颈识别:从磁盘到网络

I/O 瓶颈往往出现在数据加载和结果输出阶段。人脸识别系统里,I/O 包括:

  • 从磁盘读取图片或视频流
  • 将特征向量写入数据库
  • 通过网络传输结果

2.3.1 磁盘 I/O

用 iostat -x 1 看磁盘的 %util 和 await。如果 %util 接近 100%,说明磁盘是瓶颈。

指标 正常值 瓶颈信号
%util < 60% > 90%
await (ms) < 10 > 30
svctm (ms) < 5 > 10

我曾经遇到一个场景:人脸识别系统每秒处理 100 张图片,但磁盘是机械硬盘。结果 await 经常飙到 100ms 以上。换成 NVMe SSD 后,延迟降到 2ms,吞吐量直接翻倍。

优化建议

如果必须用 HDD,可以考虑用 direct I/O 绕过页缓存,或者用 io_uring 减少系统调用开销。嗯,不过现在 SSD 这么便宜,直接换硬件更省心。

2.3.2 网络 I/O

分布式人脸识别系统里,网络 I/O 是常见瓶颈。用 sar -n DEV 1 看网卡带宽利用率。如果超过 70%,就要考虑优化了。

我建议关注两个点:

  • TCP 重传率:超过 1% 说明网络质量差
  • 连接数:单机连接数超过 5 万,可能触发 epoll 瓶颈

说白了,网络 I/O 优化最直接的办法是:减少传输数据量。比如把图片压缩后再传,或者只传特征向量而不是整张图。

2.4 知识结构图:硬件瓶颈分析全景

下面这张图总结了硬件瓶颈分析的三个维度,以及它们之间的关联。你可以把它当作排查时的路线图。

硬件瓶颈分析全景图 硬件瓶颈分析全景图 计算单元 内存子系统 I/O 子系统 CPU 利用率 / IPC GPU 利用率 / 显存 TPU 批量推理 带宽 (stream) 延迟 (mlc) NUMA 亲和性 磁盘 iostat 网络 sar TCP 重传率 排查顺序建议 先看 I/O(最容易成为瓶颈)→ 再看内存 → 最后看计算单元 因为 I/O 问题往往掩盖了计算瓶颈,先排除外部因素

2.5 实战排查清单

最后,我整理了一份排查清单。遇到性能问题时,按这个顺序走一遍,基本能定位到根因。

  1. 先看 I/O:iostat -x 1 和 sar -n DEV 1,排除磁盘和网络瓶颈
  2. 再看内存:stream 测带宽,mlc 测延迟,numactl --hardware 看 NUMA
  3. 最后看计算:nvidia-smi 看 GPU,perf stat 看 CPU
  4. 交叉验证:用 perf top 看热点函数,确认瓶颈是否和预期一致

重要提醒

别一次性改太多参数。我见过有人同时调 batch size、换 SSD、改 NUMA 绑定,结果性能提升了,但不知道是哪个改动起了作用。一次只改一个变量,记录前后数据,这才是工程化的调优方式。