3. CXL协议基础(1):CXL.io、CXL.cache、CXL.mem三大子协议简介
聊CXL协议,很多人一上来就被它的三层架构搞懵了。说实话,我第一次看spec的时候也在想:一个互联协议,干嘛要分三个子协议?搞这么复杂干嘛?
后来在实际项目中踩过坑才明白——这三个子协议,其实是分别解决三个完全不同的问题。有点像你盖房子,CXL.io是找平地基,CXL.cache是搭承重墙,CXL.mem才是铺水管电线。缺了哪个都不行。
3.1 为什么需要三个子协议?
我们先搞清楚背景。CXL的全称是Compute Express Link,它要干的事是让CPU和加速器、内存扩展设备之间能高效通信。但高效这个词,对不同场景含义完全不同。
- 设备发现和初始化——比如你插上一块CXL内存扩展卡,系统得先认出它、分配资源。这个不需要多快,但必须可靠。
- 缓存一致性——加速器要访问CPU的缓存数据,两边必须保持同步。这需要低延迟,而且协议得复杂一点。
- 内存直接访问——把远端内存当成本地内存用,吞吐要高,延迟要低。
这三个目标,你用一套协议去cover,不是不行,但会非常臃肿。所以CXL干脆分了三个子协议,各管一摊。
| 子协议 | 核心作用 | 类似场景 |
|---|---|---|
| CXL.io | 设备发现、配置、初始化、I/O操作 | PCIe的替代升级版 |
| CXL.cache | 访问并维护CPU侧缓存一致性 | 加速器和CPU共享缓存 |
| CXL.mem | 直接读写远端内存,支持内存池化 | 内存扩展、内存共享 |
你想想看,如果没有CXL.cache,加速器每次读数据都得走主存,延迟高得离谱。如果没有CXL.mem,你想把内存扩展到远端设备,系统根本不知道那块内存在哪。
3.2 CXL.io —— 基础通道
CXL.io说白了就是PCIe的戴了CXL帽子的版本。它基于PCIe 5.0/6.0的物理层和事务层,加了CXL特有的控制逻辑。
我个人习惯把CXL.io看作是整个CXL链路的总管。它负责:
- 链路训练、初始化、热插拔
- 设备枚举和地址空间分配
- 中断、错误报告、虚通道管理
- 非一致性I/O数据传输
嗯,这里要注意:CXL.io必须始终存在。即使你的设备只用了CXL.mem,它也得先通过CXL.io把基础通路搭好。我在项目中遇到过有人只配了CXL.mem的控制器,结果忘了开CXL.io的虚通道,设备根本没法被系统识别。折腾了两天才发现问题。
3.3 CXL.cache —— 缓存一致性协议
这个就有点意思了。CXL.cache允许一个设备(比如AI加速器)直接访问并缓存CPU的cache line。关键是,它要保证一致性。
为什么会需要这个?举个例子:你有一个硬件加速器在做图像处理,它频繁读取CPU缓存里的数据。如果没有CXL.cache,加速器只能通过DMA把数据搬到自己本地内存,处理完再搬回去。一来一回,延迟翻倍。
CXL.cache让加速器可以直接发起cache请求,CPU的缓存控制器会协同处理。它定义了四种请求类型:
- RdShared —— 读共享,别人也能读
- RdUnique —— 读独占,我要改数据
- WriteUnique —— 写一份新的,其他副本无效
- WriteBack —— 把修改的数据写回
我曾经在调试一个FPGA加速器时,发现它的CXL.cache老是回写失败。查了一圈,发现是设备端的coherence engine没有正确处理snoop响应。说白了,就是CPU问它“你有没有改这块数据”,它回答错了。
3.4 CXL.mem —— 内存语义访问
CXL.mem是我最看重的子协议,也是CXL内存扩展技术的核心。它的目标很明确:让远端设备的内存,看起来就像本地DDR一样。
CXL.mem定义了两种访问模式:
- MemRd —— 从远端内存读数据
- MemWr —— 向远端内存写数据
就这么两样?对,但背后的事情可不少。CXL.mem需要解决延迟、带宽、一致性、原子操作等一堆问题。它不要求维护CPU的cache一致性,但需要保证访问顺序——也就是你写进去了,别人读到的必须是你写的内容。
我记得有个项目,客户想把CXL内存当作主存的冷数据分层。我建议他们先做延迟测试,因为CXL.mem的延迟虽然比本地内存低(相对网络),但毕竟走了物理链路和协议转换,一般会有100ns~300ns的额外延迟。这个数字做cache也许不行,做大容量内存池完全能接受。
| 对比项 | 本地内存 (DDR5) | CXL.mem 扩展内存 |
|---|---|---|
| 延迟 | ~80ns | 200ns~500ns |
| 带宽 | 单通道~40GB/s | 单链路~64GB/s(PCIe 5.0 x16) |
| 容量 | 受限DIMM槽位 | 可扩展到TB级 |
| 一致性 | 硬件保证 | 需配合CXL.cache |
3.5 三个子协议怎么配合?
很多人以为这三个协议是独立的,选一个用就行。其实不是的。CXL.device必须实现CXL.io,然后根据应用场景选择是否实现CXL.cache和CXL.mem。
比如说:
- 一个纯内存扩展设备:CXL.io + CXL.mem
- 一个有自身cache的加速器:CXL.io + CXL.cache
- 一个既要缓存一致性又要内存访问的加速器:CXL.io + CXL.cache + CXL.mem
在实际项目中,第三种情况最常见。三个子协议通过CXL链路层复用同一条物理通道,用传输层的虚通道隔离开。CXL.io走VC0,CXL.cache和CXL.mem走VC1。这样,设备发现和内存访问互不干扰。
最后,我放一张框架图,帮你把这三者的关系理清楚。
总结一句话:CXL.io是基础通道,CXL.mem是内存扩展的入口,CXL.cache是性能加速。理解好这三个子协议的分工,后面讲CXL内存扩展设备怎么设计、怎么调优,你就有了清晰的坐标系。