2. PCIe基础回顾

要定位PCIe吞吐瓶颈,必须先回到协议本身。PCIe不是一条“透明的高速导线”,而是一套严格分层的串行互连协议。一次内存读请求从CPU发出,到数据返回,中间要穿过事务层、数据链路层和物理层,每一层都有自己的封装、流控、重传和时钟域处理。吞吐瓶颈可能出现在任意一层:事务层受限于Tag数量,数据链路层受限于ACK/NAK与重传,物理层受限于链路宽度、速率和编码效率。理解分层,就是理解“瓶颈可能藏在哪里”。

一、PCIe三层结构:各司其职的流水线

PCIe协议从高到低分为三层,发送方向逐层封装,接收方向逐层解封装:

  • 事务层(Transaction Layer):负责生成和解析TLP(Transaction Layer Packet),管理请求、完成、配置、消息等事务,并维护基于Credit的流控机制。它决定“发什么、能不能发”。
  • 数据链路层(Data Link Layer):负责TLP的可靠传输,添加序列号(Sequence Number)和LCRC,生成DLLP(Data Link Layer Packet),通过ACK/NAK实现重传。它决定“发得可不可靠”。
  • 物理层(Physical Layer):负责字节条带化、加扰、编码(8b/10b或128b/130b)、串并转换、差分信号发送与接收,以及链路训练和状态机(LTSSM)。它决定“电气上能不能跑起来、跑多快”。

三层之间是服务关系:事务层把TLP交给数据链路层,数据链路层加上可靠传输信息后交给物理层;接收端则反向剥离。任何一层出现拥塞、错误或配置不当,都会直接反映为上层看到的吞吐下降或延迟抖动。

PCIe协议分层与TLP/DLLP封装关系 事务层 生成/解析 TLP Credit流控 · Tag管理 数据链路层 序列号 + LCRC ACK/NAK · 重传 · DLLP 物理层 加扰 · 编码 · 串并转换 LTSSM · 差分信号 TLP TLP + DLLP PCIe Link Lane 0 ~ Lane N Gen1/2/3/4/5 8b/10b 或 128b/130b 事务层 解析TLP · 完成匹配 返回Credit 数据链路层 校验LCRC · 序列号检查 发ACK/NAK 物理层 解扰 · 解码 · 时钟恢复 CDR · 均衡 TLP(事务层包) Header + Data + ECRC,承载Mem/IO/Cfg/Msg事务 DLLP(数据链路层包) ACK/NAK、Flow Control、Power Management,不跨链路 NAK重传

二、TLP与DLLP:两种包,两种职责

PCIe链路上传输的包分为两大类,理解它们的区别是分析吞吐问题的关键:

对比项 TLP(事务层包) DLLP(数据链路层包)
生成层 事务层 数据链路层
作用范围 端到端,跨多个链路 仅相邻两个设备之间
典型类型 Mem Read/Write、Cfg、Completion、Message ACK/NAK、InitFC、UpdateFC、PM
是否携带数据 可携带Payload 不携带用户数据
对吞吐的影响 决定有效载荷效率 占用链路带宽,影响流控与重传

TLP是“运货的卡车”,DLLP是“调度和对讲机”。DLLP本身不运数据,但它占用物理层带宽。当链路误码率升高时,NAK和重传增多,DLLP比例上升,有效吞吐就会下降。因此,分析吞吐时不能只看TLP,还要关注DLLP的开销。

三、一次内存读的完整旅程

以CPU发起一次PCIe内存读为例,数据流如下:

  1. 事务层生成Mem Read TLP,包含Requester ID、Tag、地址和长度。
  2. 数据链路层为TLP添加序列号和LCRC,放入重传缓冲区,等待发送。
  3. 物理层进行加扰、编码和串行化,通过Lane发送到对端。
  4. 对端物理层恢复时钟和数据,数据链路层校验LCRC和序列号,正确则回ACK,错误则回NAK。
  5. 对端事务层解析请求,访问目标内存,生成Completion TLP(带数据)返回。
  6. 原端收到Completion后,按Tag匹配未完成请求,释放Tag和缓冲区。

这个过程中,Tag数量决定了同一时刻能有多少个未完成读请求。如果Tag耗尽,新的读请求只能等待,链路就会出现“空转”,吞吐无法打满。这是事务层最常见的瓶颈之一。

关键认知:PCIe吞吐不是单一指标,而是“有效载荷率 × 链路速率 × 链路宽度 × 协议效率”的综合结果。协议效率又受TLP开销、DLLP开销、ACK/NAK、流控Credit和重传共同影响。

四、常见误区与复盘要点

误区一:只看链路速率,忽略编码开销。Gen3及以上使用128b/130b编码,开销约1.5%;Gen1/Gen2使用8b/10b,开销高达20%。同样标称5GT/s,实际有效带宽差异明显。
误区二:认为DLLP不占带宽。DLLP虽然小,但在高误码或深流控场景下会频繁出现,累积开销不可忽视。
误区三:忽略Tag与Credit限制。很多“链路利用率上不去”的问题,根源不在物理层,而在事务层Tag不足或Credit耗尽。

复盘时建议按层排查:先看物理层链路是否训练到预期速率和宽度,再看数据链路层是否有大量NAK和重传,最后看事务层Tag和Credit是否成为限制。只有把三层串起来看,才能准确判断瓶颈位置。

# 查看PCIe链路速率与宽度(Linux示例)
lspci -vv -s 01:00.0 | grep -E "LnkCap|LnkSta"

# 典型输出关注点:
# LnkCap: Speed 16GT/s, Width x16   ← 设备能力
# LnkSta: Speed 16GT/s, Width x16   ← 当前实际状态
# 若LnkSta低于LnkCap,优先排查物理层与LTSSM