设计工具
存储

FMS ’23:ATS/ATC 支持高性能 SSD

John Mazzie、Luca Bert | 2023 年 10 月

随着时间的推移,CPU 的计算能力呈指数级增长,而内存容量的需求增长得更快。随着 CPU 和 GPU 计算能力的激增,我们发现 AI 训练等许多工作负载现在都受到可寻址系统内存不足的限制。虽然虚拟内存(基于 SSD 的交换空间)可能在操作系统层面有所帮助(它可以防止系统因内存不足问题而崩溃),但对于在高性能工作负载中扩展内存容量而言,它不是一个理想的解决方案。

针对这一问题,一项技术解决方案是引入 Compute Express Link™(CXL),该技术允许在多个计算节点之间连接与共享内存池,使得内存可扩展性呈数量级提升(相较于本地 DRAM 而言)。它还需要根据性能和局部性对内存进行细粒度的分层,涵盖处理器缓存和 GPU 本地内存(如高带宽内存(HBM)),以及速度较慢的远内存(后者需要采用更复杂的一致性结构)。

一般来说,这种内存容量的扩展只与 DRAM + CXL 有关;存储则基本不受影响,NVMe SSD 的运行不应该受到影响,对吧? 实际情况并非完全如此。使用 SSD 时应了解分层内存,并可对其进行优化以提高高性能工作负载的性能和/或延迟。此用例中的一项 SSD 优化需要 ATS 及其相关 ATC 的支持,我们将在此处讨论。

什么是 ATS/ATC?

ATS/ATC 最相关的用途是用在虚拟化系统中。它们也可以用于非虚拟化系统,但简单说来,ATS/ATC 的工作原理是,使用 SrIOV 等标准技术,通过跟踪直接分配虚拟化系统中的虚拟机(VM)的数据路径来工作。参考示意图如下所示:

图 1 ATS/ATC 路径

虚拟化的一个关键特点是,访客虚拟机不知道它在虚拟化环境中运行。系统设备(如 SSD)认为它们正在与单个主机通信,而不是与大量 VM 通信,因此它们在 SSD 上无需额外逻辑即可正常工作。

这种方法的一个结果是内存寻址。访客操作系统设计为在专用系统上运行,因此它认为自己正在使用系统内存地址(SVA = 系统虚拟地址;SPA = 系统物理地址),但实际上它在 VM 空间中运行,由一个虚拟层管理程序管理,提供的访客地址是本地于虚拟机的,这些地址与系统的地址映射完全不同。访客操作系统认为它正在使用 SVA 和 SPA,但实际上它正在使用访客虚拟地址(GVA)和访客物理地址(GPA)。

在从本地(访客)寻址方案转换到全局(系统)寻址方案的过程中,必须小心谨慎。处理器有两种转换机制:内存管理单元(MMU)和 IOMMU,前者支持程序直接访问内存时的地址转换(与 SSD 无关),后者支持所有 DMA 传输的地址转换(这是这里的关键方面)。

如图 1 所示,每当 VM 的访客操作系统想要从 SSD 执行读取时,它必须提供 DMA 地址。它以为提供的是 SPA,实际上却是 GPA。作为 DMA 地址发送到 SSD 的只是 GPA。当 SSD 发出请求的数据时,它会发送 PCIe 数据包(称为事务层数据包 [TLP],通常大小高达 512 B),并附带 GPA。在这种情况下,IOMMU 会检查传入的地址,识别出这是 GPA,查找其转换表以确定相应的 SPA,并将 GPA 替换为 SPA,以便可以使用正确的内存地址。

我们为什么关心 NVMe 的 ATS/ATC?

系统中拥有许多 SSD 或 CXL 设备可能会导致地址转换风暴,从而堵塞 IOMMU,造成系统性能瓶颈。

例如,现代 SSD 可以执行高达 600 万次 4 KB IOPS。鉴于 TLP = 512 B,每个 IO 需要拆分为 8 个 TLP,因此有 4800 万个 TLP 需要转换。鉴于 IOMMU 每 4 台设备实例化一次,那么每秒需要转换 1.92 亿个 TLP。这是一个很大的数字,但由于 TLP 的大小“高达 512 B”(也可能更小),情况可能会更糟。如果 TLP 较小,则地址转换数量会相应地增加。

我们需要找到一种方法来减少转换数量。这就是 ATS 的作用:作为一种机制,它可提前请求地址转换,在转换有效期间可重复使用这些转换结果。鉴于操作系统的页面大小为 4 KB,每个转换结果可用于 8 个 TLP,从而成比例减少转换数量。但是页面可以是连续的,在大多数虚拟化系统中,下一个有效粒度是 2 MB,因此每个转换结果可以用于 8*2M/4K = 4096 个连续的 TLP(如果所用的 TLP 小于 512 B,则更多)。这使得 IOMMU 必须提供的转换数量可以从约 2 亿减少到远低于 10 万,从而减轻了堵塞的风险。

在 NVMe 环境中为 ATS/ATC 建模

在 NVMe 中,针对每个命令,提交队列和完成队列(SQ 和 CQ)的地址只使用一次。我们是否应该保留此类(静态)转换的副本? 一定要保留。这正是 ATC 的作用:保留最常见转换的缓存副本。

此时,主要问题是了解 SSD 将接收哪些 DMA 地址模式,以便围绕它们设计 ATS/ATC。遗憾的是,关于这些模式的数据或文献几乎不存在。

为了解决这个问题,我们开发了一款工具,用于追踪 SSD 接收到的所有地址,并将它们存储起来,以便用于建模。为了有意义,数据需要来自实际运行应用程序的一些可接受表示,并且包含足够多的数据点,以便代表一个用于缓存实现的有效数据集。

我们为一系列数据中心应用程序选择了常见的工作负载基准测试,运行它们,并为每个 20 分钟的段获取 IO 跟踪数据。这导致每条跟踪数据包含了数以亿计的数据点,用于为建模工作提供支持。

下图展示了一个数据收集示例,通过在 RocksDB 上使用 XFS 文件系统运行 YCSB(Yahoo Cloud Server Benchmark)来获得:

针对存储系统的数据 ATC 评估:

  • 表征方法:
  1. 假设 VM 正在运行标准工作负载。
  2. 跟踪每个工作负载的唯一缓冲区地址
  3. 将地址映射到 STU(2 MB)的低页面
  4. 构建 ATC 的 Python 模型
  5. 将跟踪数据重放到模型以验证命中率
  6. 对尽可能多的工作负载和配置重复以上步骤

 

图 2:收集的数据示例

观察结果:正如预期的那样,与单个图像相比,在多个 VM 中,局部性较低,但并非线性扩展(即当 #VM 数量增加到 16 倍时,缓存大小并没有相应地增加到 4 倍)

为了计算缓存需求,我们构建了一个 Python 模型来模拟缓存,重放了整个跟踪记录(共包含数亿个条目)并分析了缓存行为。通过这个模型,我们能够模拟缓存大小(行数)、驱逐策略、STU 大小以及与建模相关的任何其他参数的变化。

我们针对每个基准测试分析了约 1.5 亿到 3.7 亿个数据点,发现使用的唯一地址数量通常在数万个左右,这对于缓存大小的调整来说是一个很好的结果。如果我们进一步将它们映射到最常用的 2 MB 页面(最小传输单元,即 STU),页面数量将减少到几百个到几千个。

这表明缓冲区的重复使用率非常高,意味着即使系统内存达到 TB 级别,用于 IO 的数据缓冲区数量仍在 GB 级别,使用的地址数量也在数千个范围内,这使得该方法成为了一个不错的缓存候选方案。

我们担心高地址重用率是由特定系统配置中的局部性引起的,因此我们针对几个不同的数据应用基准测试进行了额外的测试。下表比较了上述某个 YCSB/RocksDB/XFS 基准测试与使用 XFS 的 Microsoft SQL Server 上的 TPC-H 基准测试,后者是一种截然不同的基准测试:

与 TPC-H 基准测试的相关性:

  • IO 分布迥然不同:
  1. 有 3.2 倍多的唯一地址……
  2. ……但分别在 70% 的 STU 中 -> 局部性更高
  • 当缓存大小约 64 行时,其与 RocksDB 的缓存命中率趋于一致
图 3:相关性

两者的数据跟踪完全不同,但如果缓存大小足够大(比如超过微不足道的 64 行),它们会收敛到相同的命中率。

类似发现已通过其他几个基准测试得到了验证。为了简洁起见,此处未详述。

大小依赖关系:

  • 使用的基准测试:YCSB WL B 与 Cassandra 结合使用
  • 缓存:4 路组相联
  • 算法:时间片轮转
  • 观察结果:
  1. 正如预期的那样,命中率高度取决于 STU 大小
  2. STU 越大,命中率越好
  3. 并非所有的数据都是平等的:每个 NVMe 命令都需要访问 SQ 和 CQ,因此此类地址对命中率的影响很大
图 4:大小依赖关系

数据固定和驱逐算法建模

我们还可以模拟不同算法对特殊数据固定(提交队列和完成队列)和数据替换的影响。结果如以下两幅图所示:

第一组图表验证了缓存对行大小、STU 大小的依赖关系,以及将 SQ 和 CQ 固定到 ATC 是否会有影响。对于相对较小的缓存来说,答案显然是“会有影响”。两组曲线的形状虽然非常相似,但包含 SQ/CQ 缓存的曲线在缓存较小时,其命中率起点明显更高。例如,在 STU = 2 MB 且仅有 1 个缓存行的情况下(尽管在实践中非常罕见,但有助于说明问题),不包含 SQ/CQ 缓存的命中率低于 10%,但固定住 SQ/CQ 时,命中率接近 70%。因此,这是一个很好的做法。

关于缓存性能对所选驱逐算法的敏感性,我们测试了最近最少使用(LRU)、时间片轮转(RR)和纯随机(Rand)这三种算法。如下图所示,影响可忽略不计。因此,应选择更简单、最高效的算法。

算法依赖关系:

  • 使用的基准测试:
  1. YCSB WL B 与 Cassandra 结合使用
  2. 更大集合的一部分
  • 关联性:全关联和 4 路组相联
  • 驱逐算法:LRU、随机和时间片轮转
  • 结果:
  1. 替代算法不会产生任何明显差异
  2. 选择最简单的实现可能是最有效的方法
图 5:算法依赖关系

结论

那么,我们能根据这些发现做些什么? 这种方法存在哪些差距?

这提供了一种途径,通过测量参数来定量设计 ATC 缓存,以便可以正确调整性能和设计影响。

这种方法的注意事项如下:本报告仅代表我们的初步分析,并非最终结论。例如,从 ATS/ATC 中获益最大的应用程序通常运行在虚拟化环境中,但是跟踪数据并非来自该环境。数据展示了如何弥合该差距,但这种方法更多地停留在理论原则层面,尚不能应用。因此,在进行每个 ASIC 设计时,都需要仔细考虑并做出适当的权衡。另一个要解决的差距是 ASIC 的设计需要将近 3 年时间,而新产品能够使用该设计的时间是大约 2 到 3 年,其实际使用寿命也大致相当。预测 3-7 年后工作负载的情况是一项具有挑战性的任务。那时将有多少 VM 在多少内核上运行?需要使用多少内存?

在测试中,我们找到了一条量化解决方案的道路。尽管这些未知因素看起来令人担忧,但在建模界并不罕见,任何新的 ASIC 设计都需要相应地解决这些问题。

MTS, Systems Performance Engineer

John Mazzie

John is a Member of the Technical Staff in the Data Center Workload Engineering group in Austin, TX. He graduated in 2008 from West Virginia University with his MSEE with an emphasis in wireless communications. John has worked for Dell on their storage MD3 Series of storage arrays on both the development and sustaining side. John joined Micron in 2016 where he has worked on Cassandra, MongoDB, and Ceph, and other advanced storage workloads.

DMTS - SYSTEM ARCHITECTURE

Luca Bert

Luca is a Distinguished Member of SSD System Architecture with over 30 years of Enterprise Storage experience. His focus is mainly on innovative features and their use in systems to further SSD value. He holds a Master’s Degree in Solid State Physics from University of Torino (Italy).