带宽(Bandwidth)是指在特定时间内可以传输的数据量,通常以每秒比特数(bps, bits per second)字节数(Bps, Bytes per second)来表示. 在计算机和网络系统中,带宽是衡量数据传输能力的重要指标. 较高的带宽意味着系统可以在更短的时间内传输更多的数据,这对于需要快速数据处理和传输的应用程序特别重要. 以下几个方面是带宽的重要指标:

  • 数据率(Data Rate): 通常以比特每秒(bps, bits per second)、千比特每秒(Kbps)、兆比特每秒(Mbps)、千兆比特每秒(Gbps)或太比特每秒(Tbps)来表示. 这是最直接的带宽指标,表示在单位时间内可以传输的数据量. GT/s(GigaTransfers per second,千兆传输次数每秒)是一个用于描述接口速度的指标,但它并不是直接衡量带宽的单位.
  • 吞吐量(Throughput): 实际测量的传输速率,通常低于理论最大带宽, 吞吐量受到多种因素影响,包括网络拥塞、协议开销和硬件性能
  • 信道带宽(Channel Bandwidth): 在模拟信号或无线通信中,信道带宽通常以赫兹(Hz)为单位,表示信号能够占用的频率范围. 频率范围越宽,潜在的数据传输率越高
  • 编码效率: 数据在传输过程中可能会经过编码以提高传输的可靠性和完整性. 编码效率会影响实际数据带宽, 例如 PCIe协议中的 128b/130b 编码意味着每 130 个比特中只有 128 个是有效数据
  • 多通道配置: 现代系统常通过多个并行通道传输数据, 总带宽是单通道带宽乘以通道数量, 例如 PCIe x16 插槽的总带宽是单通道的 16 倍
  • 延迟(Latency)与抖动(Jitter): 虽然延迟和抖动主要描述的是时间特性,但它们会影响实际的带宽利用率, 高延迟和高抖动可能导致带宽不足以达到其理论最大值
  • 信噪比(SNR, Signal-to-Noise Ratio): 在通信系统中,较高的信噪比能够支持更高的带宽,因为系统可以在更宽的频率范围内有效地传输数据

CXL 利用 PCIe 的物理层进行数据传输,这意味着它的带宽能力与 PCIe 的版本有关. 例如 CXL 2.0 基于 PCIe 5.0,理论上每通道的带宽可以达到 32 GT/s(千兆传输每秒),每通道的实际数据传输带宽约为4 GB/s. CXL可以通过多个 PCIe 通道来实现更高的总带宽,这对于需要大规模数据传输的应用场景特别有利. CXL 的高带宽特性使其非常适合需要快速数据传输和共享的应用,比如数据中心、AI训练和高性能计算. 因此 CXL 2.0 带宽计算如下:

  • 传输速率: CXL 2.0 基于 PCIe 5.0,每通道的传输速率为32 GT/s(千兆传输每秒), 也就是 CXL 单通道每秒传输 32G 次,也就是每秒传输 320 亿次.
  • 每传输的数据量: PCIe 5.0 在物理层使用的是 128b/130b 编码. 这意味着每 130 个比特中有 128 个比特是实际的数据位,其余 2 个比特用于编码开销. 这种编码方式提高了传输的可靠性和信号完整性.
  • 每传输bit数: PCIe 5.0 每次传输 1 bit 的数据.
# CXL2.0 PCIe5.0 单通道
CXL 单通道带宽 = 32GT/s * 1b = 32Gb/s = 32Gb/s / 8 = 4GB/s
# CXL 2.0 采用 128b/130b 编码
CXL 单通道有效带宽 = CXL 带宽 * (128/130) = 4GB/s * (128/130) = 3.93GB/s
# CXL 2.0 PCIe5.0 x16(16 通道) 带宽
CXL x16 有效带宽 = CXL 单通道有效带宽 * 16 = 3.93GB/s * 16 = 63.015GB/s
# CXL 2.0 PCIe5.0 x32(32 通道) 带宽
CXL x32 有效带宽 = CXL 单通道有效带宽 * 32 = 3.93GB/s * 32 = 125.76GB/s

相比 CXL,DDR 的带宽与计算基于其工作频率、数据总线宽度和通道数,DDR 内存(包括 DDR3、DDR4、DDR5 等)在每个时钟周期的上升沿和下降沿都传输数据,因此数据传输速率是内存时钟频率的 2 倍, 这种特性被称为”双倍数据速率”(Double Data Rate). DDR 通常使用内存频率(MT/s) 描述带宽,该单位表示每秒传输的百万次数据(Mega Transfers per second),通常与 DDR 的规格直接相关. 另外 DDR 内存的总线宽度通常是 64 位,也就是一次传输 64 bit 的数据. 例如 DDR4-3200 表示 3200 MT/s,那么其带宽计算如下:

# DDR4-3200 的频率是 3200 MT/s, 总线宽度 64bit
#  DDR4-3200 单通道带宽
DDR4-3200 单通道带宽 = 3200MT/s * 64bit = 204800Mb/s = 204.8Gb/s = 25.6GB/s
#  DDR4-3200 双通道
DDR4-3200 双通道带宽 = DDR4-3200 单通道带宽 * 2 = 25.6GB/s * 2 = 51.2GB/s
#  DDR4-3200 双通道
DDR4-3200 双通道带宽 = DDR4-3200 单通道带宽 * 4 = 25.6GB/s * 4 = 51.2GB/s

# DDR5-4800 的频率是 4800 MT/s,总线宽度 64bit
#  DDR5-4800 单通道带宽
DDR5-4800 单通道带宽 = 4800MT/s * 64bit = 307200Mb/s = 307.2Gb/s = 38.4GB/s
#  DDR5-4800 双通道
DDR5-4800 双通道带宽 = DDR5-4800 单通道带宽 * 2 = 38.4GB/s * 2 = 76.8GB/s
#  DDR4-4800 双通道
DDR5-4800 双通道带宽 = DDR4-4800 单通道带宽 * 4 = 38.4GB/s * 4 = 153.6GB/s

通过对 CXL 和 DDR 带宽计算可以看到,CXL 利用 PCIe 5.0 及更高版本的高数据传输速率(如 32 GT/s及以上),可以提供每通道高达几十 GB/s 的带宽,这使其在多通道配置下能够达到非常高的总带宽. 另外 CXL 设计的目标之一是减少延迟,特别是在内存一致性和缓存一致性方面,提供更接近 DDR 的延迟性能.

延迟(Latency) 是指从请求发出到响应返回所经历的时间,通常以纳秒(ns)或毫秒(ms)为单位,是衡量系统性能的重要指标之一. 在计算机系统中,延迟可能涵盖多个层面,例如:

  • 内存延迟: 从 CPU 向内存发出读/写请求到数据返回所需的时间
  • 网络延迟: 从数据包发送到接收所需的时间
  • 存储延迟: 从存储设备读取数据到返回的时间

CXL 是一种基于 PCIe 的互连协议,设计目标之一是提供低延迟、高带宽的通信能力. CXL 主要用于 CPU 和设备(如加速器、存储设备)之间的高效数据传输和共享内存访问. CXL 延迟的来源主要由以下部分组成:

  • 物理层延迟(Physical Layer Latency): CXL 基于 PCIe 物理层,因此继承了 PCIe 的传输延迟, PCIe 的传输延迟包括信号传输时间、串行化/解串的开销等. 现代 PCIe(例如PCIe 5.0)具有非常高的信号传输速率(32 GT/s),因此每比特的物理传输时间极低
  • 协议层延迟(Protocol Layer Latency): CXL 协议栈包括三种子协议(CXL.io、CXL.cache、CXL.mem),每种协议都引入了一定的处理开销, 例如 CXL.cache 和 CXL.mem 需要处理缓存一致性和内存访问事务. 协议层的延迟通常取决于事务的复杂性, 例如简单的 CXL.io 事务可能比复杂的 CXL.cache 事务延迟更低
  • 设备处理延迟(Device Processing Latency): 目标设备(如存储设备、内存扩展设备)需要处理 CXL 事务,并执行实际的内存读取或写入. 这部分处理延迟与设备的硬件设计有关
  • 内存访问延迟(Memory Access Latency): 如果 CXL 设备是内存扩展设备(如 DRAM 扩展模块或存储类内存),则访问该设备的延迟包括存储介质本身的访问时间. 例如 DRAM 的访问延迟通常比存储类内存(如 Optane)低得多
  • 往返时间(Round-trip Time, RTT): 请求和响应之间的物理传输时间,包括从主机到设备的传输时间和从设备返回到主机的时间
# CXL 延迟公式
CXL 延迟 = 传输延迟 + 协议处理延迟 + 设备处理延迟 + CXL 设备内部内存访问延迟
  • 传输延迟: 物理信号传输时间,通常在 PCIe 5.0 的基础上,单向传输延迟在 10 纳秒左右(具体取决于链路长度和硬件设计)
  • 协议处理延迟: CXL 协议的层级处理开销,通常在几十纳秒范围内(具体取决于事务类型和设备实现)
  • 设备处理延迟: 设备处理事务的时间,例如处理 CXL.mem 的读/写事务或 CXL.cache 的数据一致性事务, 这部分延迟取决于设备的硬件实现
  • CXL 设备内部内存访问延迟: 如果 CXL 设备是内存扩展设备,则需要计算目标存储介质的访问延迟. 例如: DRAM 通常在几十纳秒范围内(典型值为50-100ns), 存储类内存(如 Optane)的延迟通常在几微秒(us)范围内.

CXL 2.0 引入了 CXL SWITCH,在某些情况下会增加延迟,其影响主要来源于以下几个方面:

  • 数据路径的增加: CXL SWITCH 是一个额外的中间设备,数据在主机和目标设备之间需要经过 SWITCH 转发, 每一次数据包通过 SWITCH 都会引入额外的延迟,包括:
    • CXL SWITCH 转发延迟: CXL SWITCH 需要解析 CXL 协议帧,决定如何将数据包路由到目标设备, 这涉及到协议层处理和内部转发逻辑
    • Buffering 延迟: 如果 CXL SWITCH 的端口上出现拥塞(如多个设备同时访问一个目标),数据可能会被暂时缓冲,从而增加延迟.
  • 协议处理开销: CXL 是基于 PCIe 的协议,CXL SWITCH 需要解析和处理 PCIe 层数据包,并根据 CXL 协议类型(如 CXL.io、CXL.cache、CXL.mem)执行相应的操作, 这种协议处理增加了额外的延迟. CXL SWITCH 在支持内存一致性(CXL.cache 和 CXL.mem)事务时,可能需要更多的处理时间来确保一致性,这会进一步增加延迟.
  • 链路延迟: 每增加一个 CXL SWITCH,链路长度可能会增加,从而导致物理信号传输时间的增加, 尤其在多级 SWITCH 或长链路的情况下,延迟的累积效应更加显著
  • 多设备竞争: 在共享资源的情况下,多个设备通过 CXL SWITCH 同时请求访问主机或共享的内存池,这可能导致资源争用,进一步增加访问延迟

在单级 CXL SWITCH 的场景下,预计总延迟的增加通常在 10-50ns 范围内, 在多级 CXL SWITCH(CXL 3.0) 或高负载场景下,延迟的增加可能达到几十到几百纳秒, 尽管 CXL SWITCH 增加了额外的延迟,但其实际影响取决于具体实现, 以下是一些延迟分量的量化估计:

  • Switch 转发延迟: 高性能的 CXL SWITCH 通常在几纳秒(ns)到几十纳秒范围内完成转发. 例如现代 PCIe SWITCH 的转发延迟通常在 10-20ns 左右,CXL SWITCH 的延迟可能类似.
  • 链路延迟: 每一级链路的物理传输延迟一般非常低, 例如 PCIe 5.0 的单向传输延迟通常在 10ns 左右. CXL 基于 PCIe,因此物理链路延迟不会显著增加.
  • 多级 Switch 的累积延迟: 如果使用多级 CXL SWITCH(如两级或更多级别的 SWITCH),延迟会以每级 SWITCH 的转发延迟为单位累积. 例如两级 SWITCH 可能引入 20-40ns 的额外延迟.
  • 资源争用和拥塞: 在高负载情况下,CXL SWITCH 的内部缓冲和仲裁机制可能引入额外的延迟,这部分延迟与工作负载的使用模式密切相关

DDR 内存的延迟可以从多个方面进行衡量,主要包括时钟周期延迟、实际时间延迟以及影响延迟的因素. DDR 内存的延迟通常用几个关键参数来表示,这些参数以时钟周期为单位:

  • CAS Latency (CL): 这是 Column Address Strobe Latency, 表示从内存控制器发出请求到数据准备好可用之间的时钟周期数, CAS Latency 是 DDR 延迟的一个关键指标.
  • tRCD(Row Address to Column Address Delay): 这是从行地址被选中到列地址被选中之间的时钟周期数
  • tRP(Row Precharge Time): 这是关闭一行并打开下一行所需的时钟周期数
  • tRAS(Row Active Time): 这是一行必须保持激活状态的最小时钟周期数

实际的时间延迟可以通过将时钟周期延迟乘以内存时钟周期的时间得到, 内存时钟周期的时间(以纳秒为单位)是 DDR 内存的频率(以 MHz 为单位)的倒数, 例如:

# DDR4-3200:
# 内存时钟频率是 1600 MHz(因为 DDR 是双倍数据速率,每个时钟周期传输两次数据,所以实际频率是 3200/2)
时钟周期时间 = 1 / 1600 MHz = 0.625 ns
# 如果 CAS Latency(CL) = 16
CAS 延迟时间 = 16 × 0.625 ns = 10 ns

通过对 CXL 和 DDR 延迟计算逻辑进行分析之后,DDR 延迟通常显著低于 CXL 延迟,DDR 适用于对时延极为敏感的应用,如传统的计算任务和实时应用. CXL 延迟通常较高,但 CXL 提供更高的带宽和更大的灵活性,特别适合需要内存池化和异构计算的场景. 为了更好的对 CXL 的带宽和延迟有感觉,接下来通过一个实践案例边实践边讲解.

图片无法显示,请右键点击新窗口打开图片

BiscuitOS 目前支持 CXL2.0 SWITCH 的实践,本节用于介绍如何在 BiscuitOS 上实践上图所示的 CXL 拓扑, 项目包含了一台主机,CPU 通过南桥转 CXL Host Bridge,其引入 PCI:0C 总线,直接连接到 CXL Root Complex,CXL RC 里仅包含一个 CXL RootPort,此时 CXL RootPort 的 BDF 为 “0C:00.0”. RP 通过 “BUS-D” 总线连接到 CXL SWITCH 上,SWITCH 只虚拟了一个 VCS,那么 Upstream Port(UP vPPB) 的 BDF 为 “0D:00.0”, VCS 通过 “BUS-E” 总线连接 4 个 Downstream Port(DP vPPB), 每个 DP 都连接到一个 PCIe 插槽上. 实践案例里只有 “BUS-F” 连接的 PCIe 插槽上插入一个 “CXL Type3” 设备,该设备的 BDF 为 “0F:00.0”. 接下来在 BiscuitOS 实践该场景, 参考如下命令:

# 切换到 BiscuitOS 项目目录
cd /BiscuitOS
# 选择开发环境,如果已经选择过可以跳过,这里与 linux 6.10 X86 为例
make linux-6.10-x86_64_defconfig
# 通过 Kbuild 选择需要部署的应用程序
make menuconfig

  [*] DIY BiscuitOS/Broiler Hardware  --->
      [*] CXL: Compute Express Link
            CXL Hardware Topology (CXL2.0: x1 VCS + x1 Type3 PMEM)  --->
      [*] CXL LIMIT Bandwidth
      (100)  CXL READ Bandwidth(MiB)
      (200)  CXL WRITE Bandwidth(MiB)
  [*] Package  --->
      [*] HETEROGENEOUS MEMORY MANAGEMENT
          [*] CXL BANDWIDTH  --->

# 配置完毕保存,然后进行部署
make

# 切换到实践案例所在目录
cd output/linux-6.10-x86_64/package/BiscuitOS-CXL-BW-default
# 准备依赖工具
make prepare
# 编译实践案例
make download
make build

图片无法显示,请右键点击新窗口打开图片

当 BiscuitOS 启动之后,直接运行 RunBiscuitOS.sh 脚本,脚本会构造测试所需的环境,运行完毕之后,CXL 内存会以 FSDAX 的形态挂载到 “/mnt/DAX” 目录下,可以在该目录下执行带宽相关的测试工具,比如直接使用 dd 命令测试读写带宽。另外测试用例还提供了一个动态调节 CXL 带宽的工具,该工具需要再虚拟机启动之后,打开另外一个终端,在终端中按下面命令进行CXL 带宽调整:

# 切换到实践案例所在目录
cd /BiscuitOS/output/linux-6.10-x86_64/package/BiscuitOS-CXL-BW-default/BiscuitOS-CXL-BW-default
# 调整 CXL 带宽命令格式
#  ./FManger.sh -r <RBPS> -w <WBPS>
#  RBPS: 读带宽,单位是 MB
#  WBPS: 写带宽,单位是 MB
./FManger.sh -r 20 -w 40

调整完毕之后,再次在 “/mnt/DAX” 目录下进行测试. 由于上面的操作都是通过软件模拟,无法真实展示出 CXL 带宽,接下来会从网络上和一些论文里摘取一些 CXL 带宽相关的数据和内容进行分析.

图片无法显示,请右键点击新窗口打开图片

Intel 第 4 代 Xeon SPR 开始支持 CXL1.0/CXL1.1, 测试数据来自 Intel SPR CPU 和基于 Intel Agilex-I FPGA 的 CXL存储器(R-Tile 中加固的 CXL 控制器)组成的测试台上. 对具有多个微基准和端到端应用程序的 CXL 内存进行了全面分析. 从微基准标记中发现 CXL 内存的行为与远程 NUMA 节点中的内存不同,后者通常用于仿真. 与基于 NUMA 的内存相比,真正的 CXL 内存具有:

  • 更高的延迟
  • 更少的内存通道(导致更低的吞吐量)
  • 在各种操作下不同的传输效率

基于上述观察,还将 CXL 内存应用于表现出不同内存访问行为的三个实际应用程序. 发现对 CXL 内存卸载有不同的敏感性.

  • μs延迟数据库对内存延迟的增加高度敏感
  • 当数据库在 CXL 内存上运行时,具有中间计算层的 ms 延迟微服务受到的影响较小
  • 内存密集型 ML 推理对 CXL 内存提供的随机访问吞吐量敏感
  • 在所有情况下,在连接 CPU 的 DRAM 和 CXL 内存之间交错内存可以减少 CXL 内存带来的性能损失

在测试中,使用两个测试台来评估最新的商品 CXL 硬件,平台 A 配备 Intel Gold 6414U CPU 和 128 GB CXL.mem 协议以及 4800MT/s DDR5 DRAM(分布在 8 个内存通道中). 在第 4 代中,Intel Xeon CPU 被实现为四个单独的小芯片, 用户可以决定使用这 4 个小芯片作为统一处理器(即共享的末级缓存(LLC)、集成内存控制器(iMC)和根复合体),或者在子 NUMA 集群(SNC)模式下,每个小芯片作为一个小 NUMA 节点运行. 这种灵活性允许用户微调系统以适应其工作负载特性,并对资源共享和隔离进行细粒度控制. 在该平台 A 将探索 SNC 和 CXL.mem 之间的内存交错将如何影响应用程序的性能. 平台 B 则是双插槽系统上具有两个 Intel Platinum 8460H 和相同的 DDR5 DRAM,以在基于 NUMA 的常规内存和 CXL.mem 之间进行一些比较.

图片无法显示,请右键点击新窗口打开图片

对于 CXL 内存设备,系统有一个 Intel Agilex-I 开发套件, 它具有 16GB 2666MT/s DDR4 DRAM 作为 CXL 内存,并通过 x16 PCIe Gen5 接口连接到 CPU. 它作为一个具有 16GB 内存的 CPULESS NUMA 节点透明地暴露给 CPU 和 OS,并且 CXL 内存的使用与常规的基于 NUMA 的内存管理相同.

为了彻底检查 CXL 内存的能力,开发了一个称为 MEMO 的微基准测试, 此基准测试旨在针对 CXL 内存的各种用例,并在 Linux 用户空间上运行, 用户可以提供命令行参数来指定 MEMO 要执行的工作负载. 特别地,MEMO 具有以下能力:

  • 通过使用 NUMA_lalloc_node 函数从不同的源分配内存,包括本地 DDR5 内存、CXL 内存无 CPU NUMA 节点或远程 DDR5
  • 启动指定数量的测试线程,将每个线程固定到一个内核,并可选地启用或禁用内核
  • 使用内联汇编语言执行存储器访问

基准测试报告不同指令(如加载、存储和非临时存储)的内存访问延迟或聚合带宽,所有内存访问都使用 AVX-512 指令完成. 此外 MEMO 可以在内存区域上执行指针跟踪,并且通过改变工作集大小(WSS),基准可以显示平均访问延迟如何随着 WSS 跨越缓存层次结构的不同大小而变化.

图片无法显示,请右键点击新窗口打开图片