摘要

像NVDIMM这样的大容量持久存储器一直被认为是一种开创性的存储器技术,因为它们即使在断电后也能维持系统的状态,并允许系统快速恢复。然而,由大量的软件栈干预引起的开销严重地抵消了这种内存的好处。首先,为了显著减少软件堆栈开销,我们提出了HAMS,一种硬件自动化的存储上内存(MoS)解决方案。具体来说,HAMS将NVDIMM和超低延迟flash卷(ULL-Flash)的容量聚集到一个大的内存空间中,这些内存空间可以作为工作内存扩展或持久内存扩展,以一种os透明的方式使用。HAMS位于内存控制器集线器中,并通过传统的DDR和NVMe接口管理其MoS地址池;它使用一个简单的硬件缓存,将ull-flash的存储空间映射到NVDIMM的内存空间后,服务于主机MMU的所有内存请求。其次,为了提高HAMS的效率和可靠性,我们提出了一种“高级HAMS”,通过优化HAMS的数据路径和硬件模块,消除NVDIMM和ull-flash之间不必要的数据传输。这种方法从存储盒释放ull-flash及其NVMe控制器,并通过传统的DDR4接口直接将HAMS数据路径连接到NVDIMM。我们的评估显示,与基于软件的NVDIMM设计相比,HAMS和高级HAMS可以提供97%和119%的系统性能,而能耗分别降低41%和45%。

1. 引言

最近,诸如PRAM和3D XPoint等持久性存储器受到了相当大的关注,因为它们的固有非易失性、高密度和低功耗可以使现代数据中心和高性能计算机受益。对于这样的系统,需要后端存储来从系统故障和崩溃中恢复。由于持久内存可以自发地瞬时恢复所有内存状态,它们可以消除对后端存储的大量访问和相关的运行时开销。此外,企业工作站和服务器使用DirectAccess (DAX)的持久内存,这带来了前所未有的性能水平和数据弹性的优势。

有三种标准的持久内存类型(即NVDIMM-N/F/P)。NVDIMM-F将flash直接集成到DIMM (dual-inline memory module)中,提供类似存储的高容量。但是,NVDIMM-F不能简单地代替DRAM,因为它只暴露了一个块接口。NVDIMM-P如Optane DC PMM是字节可寻址的,但它使用应用程序直接模式来支持数据持久性的性能仍然比DRAM差6倍。相反,NVDIMM-N的目标是提供“字节可寻址”的持久性,具有类似于DRAM的性能。NVDIMM-N通常由一个小型闪存设备和多个带有电池的DRAM模块组成。NVDIMM-N可用于广泛的数据密集型应用,如数据库管理系统(DBMS)[2]、事务处理[45]、[63]、数据分析[8]和检查点[12]。但nvdimm - n (4GB ~ 64GB)的内存空间比NVDIMM-P和ssd等持久性存储设备要小得多。此外,NVDIMM-Ns中的DRAM容量受到电池规模不佳的限制,当电源故障发生[5]时,需要为DRAM备份操作提供电源,[71]。例如,在过去的二十年里,DRAM的存储密度增加了许多数量级,而锂离子电池的能量密度只增加了三倍[34]。

要构建一个大型的、可扩展的、持久的内存空间,一个可能的解决方案是将NVDIMM-N与SSD和内存映射文件(MMFs)一起使用,这些文件可以在操作系统内存管理器或文件系统中实现。这允许数据密集型应用程序使用传统的负载/存储指令访问大的存储空间。然而,我们观察到,与仅使用nvdimm-n的解决方案相比,这种mmf辅助的持久内存在用户级平均会降低48%的应用程序性能(参见第III-B节)。这种严重的性能下降不仅是由于访问SSD时的长失速延迟,而且在传统存储堆栈中,软件开销和用户和系统内存空间之间频繁的数据复制。

为了解决上述限制,我们提出了HAMS,一种硬件自动存储(MoS)解决方案,它聚合了NVDIMMN的内存容量和新的超低延迟flash存档的存储容量,被称为ull-flash [37], [68],集成为一个大内存空间(见图1)。HAMS的大单片内存空间可以用作工作内存或持久性内存扩展。我们的HAMS位于内存控制器集线器中,并通过利用传统的DDR4和NVMe接口来管理其MoS地址池。为此,通过将ull-flash的存储空间映射到NVDIMM-N的内存空间,HAMS使用了一个简单的硬件缓存来处理来自主机内存管理单元(MMU)的所有内存请求。在NVDIMM-N缓存缺失的情况下,HAMS在内部管理NVMe命令和I/O请求队列,同时隐藏操作系统的所有NVMe协议和接口管理开销,这样MMU请求的数据总是由NVDIMM-N提供。

虽然HAMS的“基线”设计可以提供20GB/s的峰值带宽,但它仍然可以产生次优的系统性能,特别是在运行大规模数据密集型应用程序时,由于一些效率低下,下文将介绍。首先,处理NVDIMM-N的cache miss需要在NVDIMM-N和ull-flash之间进行数据传输。也就是说,HAMS需要通过DDR4和PCIe接口(包括物理层、控制器和协议管理器)来处理NVDIMM-N缓存丢失。然而,PCIe带宽不足以向HAMS展示ull-flash的全部潜力。因此,对于大型数据密集型应用程序,为了处理频繁的NVDIMM-N缓存丢失而进行的数据传输可能会造成高达47%的HAMS内存访问延迟。其次,一些数据可能冗余地存在于NVDIMM-N和ULLFlash的内部DRAM中,用作缓存和/或缓冲区。例如,大多数现代ssd,包括ULL-Flash,使用大型内部DRAM来缓冲/缓存所有传入的I/O请求,以隐藏底层flash的长延迟。这将有助于ssd在块存储文件系统中提高性能,但在基于mos的解决方案中使用ssd会浪费电力,并增加ssd的内部复杂性。

为了解决这些局限性,我们还建议通过修改其数据路径和硬件模块,将其积极集成到现有的计算机系统中。就数据持久性而言,这使得基线解决方案更加节能和可靠。这种“高级HAMS”从存储盒中释放ULL-Flash及其NVMe控制器,并将它们的数据路径直接连接到NVDIMM-N。为此,我们建议稍微修改ull-flash中的NVMe控制器,方法是合并一个新的基于寄存器的接口,并将该接口与HAMS的DDR4接口紧密集成。这种积极的集成允许ull-flash访问NVDIMM-N中的DRAM设备,而不需要来自HAMS的任何干预,并从ull-flash中删除DRAM缓冲区,同时启用完整的NVMe功能。

我们的评估结果显示,与基于mmf的NVDIMM-N+SSD混合设计相比,HAMS和高级HAMS提供了97%和119%的系统性能,同时消耗的系统能量分别减少41%和45%。

2. 背景

在本节中,我们首先描述持久内存的关键硬件组件和异构内存扩展的存储堆栈。接下来,我们给出了ull-flash的硬件和固件细节。

2.A 持久内存与存储

图2描述了一个系统架构的高级视图,其中包括NVDIMM-N/P和ULL-Flash。NVDIMM-N/P通过DDR内存总线连接到MCH (memory controller hub),作为CPU的标准注册内存(RDIMM),而ull-flash通过PCIe根complex连接到MCH作为块存储。

持久的记忆:持久内存有三种标准版本:NVDIMM-N[31]、-F[54]和-P[16]。表1总结了这三种类型的持久内存和我们的设计之间的关键区别。NVDIMM-N是针对持久内存模块的JEDEC标准,它包括DRAM设备、超级电容、多路复用器和小型flash设备。超级电容被用作DRAM备份操作的能源,当电源故障发生时。多路复用器位于DRAM和标准内存连接器到内存总线之间,当发生备份和恢复操作时,它们将DRAM与内存总线隔离。闪存作为备份存储介质,与DRAM具有相同的容量,但对用户是不可见的。当主机直接访问NVDIMM-N的DRAM时,它的控制器在电源故障时内部将DRAM数据迁移到闪存,这种迁移通常需要数十秒[31]。控制器在下一次引导时将数据从闪存恢复到DRAM,从而提供非易变性。相反,NVDIMM-F由多个不带DRAM的闪存组成。由于NVDIMM-F通常用作块存储,因此它需要文件系统和操作系统的支持,类似于传统的ssd。NVDIMM-P结合了NVDIMM-N和NVDIMM-F的设计策略,采用了字节可寻址接口。然而,像Optane DC PMM这样的NVDIMM-P比DRAM表现出6×lower的性能,并且不允许直接访问其内部DRAM,并且需要操作系统级别的支持来实现持久内存访问。到目前为止,这使得NVDIMM-N成为唯一支持具有字节可寻址性的DRAM性能的持久内存。考虑到这一点,在本文中,我们交替使用术语“NVDIMM”和“NVDIMM-n”。

存储:所有高性能ssd,包括ULLFlash,都连接到MCH的另一部分,PCIe根复合体。在现代计算机系统中,PCIe通道也被视为内存总线,但它在CPU和SSD之间为I/O事务传输4KB或更大的数据包。由于I/O访问的粒度是一个页面或一个块,用户应用程序只能通过操作系统的整个存储堆栈访问底层SSD,其中包括一个NVMe驱动程序之上的I/O运行时库、文件系统和块层。NVMe驱动程序管理PCIe上的数据包传输,并通过PCIebaseline地址寄存器(bar)与SSD中的NVMe控制器通信,这些地址寄存器包括门铃寄存器、队列属性、每个队列的目标地址以及NVMe控制器信息[10]。ull-flash的内部硬件细节将在II-C节中解释。

2.B 持久内存扩展的支持

图3展示了用户应用程序将NVDIMM扩展为SSD所需的软件支持和存储堆栈。Linux系统中的MMF (memory-mapped file)模块,也称为mmap,可以用SSD来扩展NVDIMM的持久内存空间。如果一个进程对SSD(1)调用带有文件描述符(fd)的mmap, MMF在它的进程地址空间中创建一个新的映射,由一个内存管理结构(mm_struct)表示,通过分配一个虚拟内存区域(VMA)给该结构(2)。换句话说,MMF连接fd到VMA,通过在进程内存和目标文件之间建立一个映射。当进程访问VMA(345)指定的内存时,会触发页面错误(如果NVDIMM中没有可用的数据)。

当发生页面错误时,将调用页面错误处理程序并将一个新页面分配给VMA。由于VMA链接到目标文件,页面错误处理程序检索与fd关联的文件元数据(inode),为其访问获取一个锁(6)。MMU与文件系统的错误处理程序交互,从SSD读取页面。文件系统初始化一个块I/O请求结构,称为bio,并将其提交给多队列块I/O队列(blkmq)层,该层通过多个软件队列调度I/O请求(7)。队列可以被映射到一个或多个软件硬件调度队列(8),由NVM控制器存在的SSD(9)内一旦I / O请求的服务(例如,生物)完成后,和实际的数据加载到一个新的区域的内存分配页面,页面错误处理程序创建一个页表条目(PTE),在PTE中记录新的页面地址,然后继续该进程。

MMF可以和ssd盘一起扩展NVDIMM的持久内存空间。然而,由于页面错误、文件系统、上下文切换和数据复制造成的高开销,这种方法可能会抵消ull-flash带来的大部分好处。

2.C ULL-Flash

硬件细节:所有最先进的ssd通常使用大量闪存包,并将它们连接到多个系统总线,即channels。每个flash包包含多个模具和平面,以实现快速响应和低延迟,如图4a所示。为了提供大量的并行性和高I/O性能,SSD将主机上的给定I/O请求分散到多个通道、包、die甚至平面上。

ull-flash也采用了这种多通道多路架构,但对数据路径和通道剥离[9]进行了优化。更具体地说,ULL-Flash将来自主机的4KB I/O请求拆分为两个操作,并同时将它们发送给两个通道;这样做可以有效地将DMA延迟减少一半。此外,虽然大多数高性能ssd采用多水平单元(MLC)或三水平单元(TLC),但ULL-Flash采用一种新型的flash介质,称为z-nand[9]。Z-NAND利用3d flash结构提供单层单元(SLC)技术,并优化I/O电路和内存接口,以实现短延迟。具体来说,Z-NAND使用了48个堆叠的字线层,被称为垂直NAND (V-NAND)架构,以体现SLC内存。由于其独特的闪存结构和先进的制造技术,Z-NAND闪存(3 μ s和100 μ s)的读写时延为15×and 7×lower,而V-NAND闪存的读写时延为[55]。

ull-flash在其多个通道前使用大DRAM,并通过NVMe接口公开其内部并行性、低延迟和高带宽,这些都由多个接口控制器和固件模块管理。请注意,DRAM管理与NVMe协议的处理是紧密耦合的。根据NVMe的定义,在底层的ull-flash控制器或固件执行DMA进行数据传输之后,主机端DRAM和ssd内部DRAM中都可以存在相同的数据。

连接到CPU的I/O:图4b展示了每核NVMe队列和通信协议。NVMe队列由一对提交队列(SQ)和完成队列(CQ)组成,每个队列都有64K条目[22]。这些是简单的FIFO队列,每个条目都由物理区域页面(PRP)指针[10]引用。如果请求的大小大于一个4KB的NVMe包,则可以通过一组PRP指针而不是单个PRP指针来引用数据。当请求到达SQ时,主机增加其尾部(指针)并按下相应的ull-flash门铃,NVMe控制器就可以同步存储侧SQ,存储侧SQ在逻辑上与主机侧SQ配对。由于每个条目的数据都存在于主机端DRAM中(由PRP指针指向),因此ull-flash为I/O请求处理DMA,然后底层的Z-NAND和固件为请求服务。一旦服务完成,NVMe控制器移动CQ的尾部(与SQ配对),并通过消息通知中断(MSI)通知主机事件。然后,主机跳转到中断服务程序(ISR),并同步CQ尾部。ISR完成请求,推进CQ的头(并释放缓冲区数据),并按门铃通知ull-flash主机端I/O处理完成。最后,NVMe控制器释放内部数据,推进CQ的头指针。NVMe接口不知道缓存在主机端DRAM中的数据,而每个I/O请求的数据可以驻留在主机端DRAM中。因此,即使主机端DRAM可以处理I/O请求,NVMe接口也会毫不相干地将请求排队并处理它们。

固件:图4c显示了在ull-flash中实现的通用固件架构。在ull-flash的固件层的顶部,主机接口层(HIL)负责解析NVMe命令,并通过与内部NVMe控制器[32]协作来管理队列。这一层还将I/O请求(可以是任意长度的)拆分为子请求。子请求的大小与底层固件模块管理的单元I/O大小匹配。被解析的独立请求被转发到flash翻译层(FTL)[35]。FTL将给定的逻辑块地址(LBA)转换为物理页码(PPN)。在将每个子请求的地址转换为PPN后,flash接口层(FIL)提交请求并管理其事务,这些事务由行/列地址、I/O命令、管理命令和DMA传输等多个flash命令组成。在这个I/O处理过程中,FTL/FIL可以跨多个内部资源(如通道、包、芯片、平面等)将请求分条处理,实现低延迟和高带宽。

3. 动机和挑战

在本节中,我们将解释为什么ull-flash可以用于大型工作内存解决方案,并讨论传统的软件辅助解决方案在集成NVDIMM和ull-flash来扩展持久内存时面临的挑战。

3.A ULL-Flash性能表征

我们评估了真正的800gb z-ssd原型机([56]为ull-flash),并分析了其性能特点。然后,我们使用Flexible I/O Tester[3]比较了ull-flash与高性能NVMe SSD (Intel NVMe 750[25])的性能特征。这两种设备都使用4个PCIe3.0通道(1GB/通道),并由一个具有单个4GHz CPU[23]的系统进行评估。在顺序和随机读/写访问下,收集到的性能特征如图5所示。我们还评估了不同的I/O队列深度(1 ~ 32)的性能。请求大小等于NVMe数据包有效负载的大小(4KB)。

如图5a所示,我们观察到ull-flash在用户级的4KB读写时延为8个µs和10个µs,队列深度为1~4。也就是说,ull-flash的这种读写时延仅比同一测试台上单个DDR42133 DIMM[64]的实际读写时延(4kb大小)长3.3×and 79%。这种显著的延迟优势使ull-flash有望取代传统的SSD,以扩展NVDIMM的持久内存空间与存储。如图5b所示,在不同I/O深度下,ULLFlash能够以可预测和可持续的方式保持这种延迟特性,而NVMe SSD的延迟随着I/O深度的增加而显著增加(最高可达155µs)。图5c比较了ULL-Flash和NVMe SSD的带宽趋势。对于读和写访问,ULL-Flash提供了比NVMe SSD高115%和137%的平均带宽。这些图还表明,ULL-Flash仅用几个NVMe命令就能达到峰值带宽,而NVMe SSD在随机读访问时不能达到峰值带宽,即使我们将队列深度增加到32个条目。我们还观察到,对于大多数访问,在ull-flash等待队列中的请求数是4(参见图5c)。仅支持16个未处理的随机读请求。我们相信,这种特性可以使NVMe队列管理变得简单,并且易于在硬件上实现。

3.B 基于软件的内存扩展

为了评估现有基于软件的内存扩展的性能,我们使用真实设备配置一个基于mmf的主机系统。我们的评估系统集成了3个SSD(包括SATA SSD[24],以及ull-flash和NVMe SSD),并采用了两个8GB DRAM rank,每个rank有8个bank运行在1.6GHz。ull-flash使用mmap扩展内存空间。

基准:我们使用了mmap-benchmark,它被设计成通过一组微基准[33]来评估mmap的性能。每个seqRd和seqWr创建一个线程,然后执行顺序的读和写操作。相比之下,每个rndRd和rndWr创建4个线程,每个线程同时执行随机的读和写操作。我们还测试了sqlite-benchmark,这是一个广泛使用的DBMS (SQLite)[14]的基准。工作量的详细情况将在第6-a节中说明。

性能:图6a和图6b分别显示了mmap-benchmark(带宽)和sqlite(事务延迟)的性能。如图6a所示,在mmf系统中,ULL-Flash的带宽比SATA和NVMe ssd分别高出399%和118%。seqRd和seqwr在ssd的峰值带宽附近表现出性能,但当执行rndrd和rndwr时,性能显著下降。这是因为seqrd和seqwr以顺序的方式将数据拉到文件系统的缓冲区缓存中,这有助于我们隐藏ssd在基于字节的I/O访问时的性能下降。此外,mmap-benchmark和sqlite的平均I/O队列深度分别为1和4,这可以更好地利用预读的好处。同样,图6b显示,ULLFlash forSQLite(每个事务)的平均延迟比SATA和NVMe ssd分别低95%和72%。

ULL-Flash开销分析:图7a进一步将用户应用程序的总执行时间分解为mmap处理时间(即上下文切换和页面错误处理)、I/O堆栈时间(即文件系统、blk-mq层和NVMe驱动程序)、ull-flash访问时间和应用程序计算时间。为了更好地理解,该图还分析了与基于nvdimm的系统相比,基于ull-flash的MMF系统对整体性能的降低程度。因为rndsel和seqsel的大部分执行都是在dbms端计算,平均而言,它们的CPU周期占总执行时间的83%。然而,mmap-benchmark和sqlite剩下的工作负载分别占执行的13%和53%,而平均而言,ULL-Flash只占总延迟的13%。注意,由MMF(mmapand I/O堆栈)强加的系统开销占总执行时间的69%。这是因为MMF涉及许多软件操作,包括多页故障处理、上下文切换、地址转换(例如,页表、文件系统和FTL)、边界检查和权限检查[20]。上下文切换是增加I/O延迟[40]的主要原因之一。另一方面,I/O堆栈中的排队机制和NVMe通信协议被优化为吞吐量而不是I/O延迟[68]。MMF的软件运行时间为15 ~ 20 us[20],比ZNAND的访问延迟(3us)长约6倍。

3.C 软件开销

为了消除由MMF带来的软件开销,我们可以绕过整个存储堆栈,将底层的ULL模拟为一个内存模块,直接为加载/存储指令提供服务。图7b显示了三种不同bypass策略的cpu端性能:(1)仅NVDIMM (NVDIMM), (2) ULL-flash (ULL),和(3)带有页面缓冲区(本质上是一个小DRAM (ull-buff))的ULL-flash。在此评估中,我们使用与第III-B节相同的工作负载。使用mmap-benchmark收集的结果表明,基于ull和ull-buff的系统的平均每周期指令(IPC)值分别仅为0.001和0.003,而基于vdimm的系统的平均IPC值为0.06(即98%和95%的降级)。

在评估sqlite时,我们观察到ull和ull-buff相比于DRAM降低了140x和101x的IPC。加载和存储指令占执行指令总数的51%,我们测试的工作负载中的所有这些加载/存储指令都是由于相对较长的ull-flash操作。需要注意的是,ZNAND的延迟(3µs)比传统的flash短很多,但比NVDIMM的4KB访问延迟3.3×longer。虽然页面缓存可能隐藏页面访问延迟,但我们观察到,由于mmap-benchmark和sqlite显示的糟糕的数据局域性,很大一部分加载/存储指令都受到页面缓存丢失的影响。

HAMS的目标是:(1)从mmf系统中移除mmap和存储堆栈开销;(2)通过在NVDIMM中直接缓存内存引用和自动化ULL-Flash和NVDIMM之间的映射来减少停止指令的数量。

4. 存储上内存

HAMS的目标是通过集成NVDIMM和ull-flash来自动化所有扩展持久内存所需的硬件,同时减少能源消耗并保持由此产生的异构内存空间的一致性。在本节中,我们概述了基线设计和HAMS的积极整合。

4.A HAMS总览

图8显示了HAMS的基本架构。HAMS驻留在MCH中,MCH实现了地址管理器、NVDIMM内存控制器和PCIe根复合体。地址管理器通过将ull-flash的存储容量暴露给MMU,提供了一个64位的字节可寻址地址空间。它还利用NVDIMM的内存空间作为一个包含缓存的ull-flash与集成的标签阵列。为了实现MoS,地址管理器使用一个简单的硬件缓存逻辑,协调NVDIMM和ull-flash来服务传入的内存请求。请注意,内存请求可以由MMU或ull-flash生成,因此,它们应该以不同的方式处理。当NVMe控制器(在ull-flash中)生成内存请求时,NVMe控制器通过地址管理器处理的PRP(s)提取目标数据的NVDIMM地址,并记录在请求中。然后,HAMS根据记录的NVDIMM地址直接转发访问NVDIMM的请求。另一方面,HAMS通过检查MMU的MoS标签阵列来检查MMU请求的存储地址。如果请求的内存地址在MoS标签阵列中命中,则该请求直接由NVDIMM的数据提供服务。否则,HAMS通过将数据驱逐到ull-flash来保护NVDIMM空间以容纳传入的请求。HAMS也从ULL-Flash中获取目标数据到NVDIMM,用于读请求。一旦数据从ULL-Flash传输到NVIDMM(或反之)完成,HAMS通知MMU完成,以便MMU可以重试停止的指令。

4.B ULL-Flash档案管理

持续控制的电源故障管理是HAMS关键设计的核心。NVDIMM的数据由其板载NVM控制器存储和恢复,而NVMe存储则采用不同的机制来处理掉电故障。具体来说,SSD的数据持久性和I/O原子性是由文件系统来保证的。文件系统和其他内核相关组件通常使用日志记录来支持持久性[65]。由于HAMS删除了对MMF和文件系统的支持,ssd内部DRAM中的数据可能在断电时丢失。虽然HAMS可以通过标记每个请求[60]的强制单元访问(FUA)来加强数据持久性,但这样做会显著降低ULL-Flash的性能。这是因为FUA强制将所有未处理的请求序列化到底层flash介质。HAMS设计中的另一个问题与NVMe协议的硬件实现有关。由于NVMe数据结构(包括SQs、CQs和bar)被映射到NVDIMM的内存区域,所有数据和队列信息都可能被任何用户应用程序或操作系统无意中覆盖。这使得HAMS中基于硬件的NVMe管理变得脆弱。另外,如果HAMS和ull-flash同时访问同一页框,NVDIMM中的数据可能不一致。

我们提出了一套解决上述挑战的方案。具体来说,为了保护数据不受电源故障的影响,我们在ULL-Flash中集成了超级电容来将volatile DRAM缓冲区中的数据刷新到持久闪存介质中。我们还利用NVMe数据结构来恢复由于功率损失而损坏的I/O请求。另一方面,为了解决NVMe数据结构的漏洞问题,我们在NVDIMM中固定一个特定的内存区域来存储NVMe数据结构,使其对MMU不可见。如图9所示,这个固定内存区域包括用于SQs和CQs、PRP池和MSI表的环形缓冲区,它被映射到NVDIMM的上内存部分(在我们的设计中约为512MB)。另一方面,将NVDIMM剩余的内存区域通过HAMS映射到MoS地址空间。在初始化过程中,HAMS检查固定的内存区域,特别是SQ和CQ缓冲区,包括头和尾指针。如果没有断电,则SQ和CQ尾部指针应该指向它们的队列项的相同偏移量,以避免违反NVMe队列管理和一致性[21]。然而,如果出现电源故障,HAMS是能够检测所有挂起的请求,通过检查NVDIMM的MMU-不可见空间中的SQ/CQ尾指针的偏移量差异 (图9)。在电力恢复期间,HAMS需要补发所有未决请求到ULL-Flash,以保证数据持久性和一致性。为了保护数据传输到的内存,HAMS通过为MoS标记阵列的每个条目配置一个位来跟踪DMA状态,这被称为繁忙位。每当NVMe引擎发出命令时,该位就被设置为1,并且当HAMS更新CQ的头指针时可以清除该位。因此,如果设置了忙位,那么HAMS将放置相应页面被逐出。这保证了当ull-flash通过PRP访问页面框架时,数据是一致的。

4.C 积极整合HAMS

迄今为止解释的HAMS的基本设计包括在MCH中利用传统的DDR和PCIe控制器实现缓存逻辑的硬件自动化,从而提供了大的工作内存空间。虽然这种设计策略不需要对现有的存储和存储设备进行任何修改,但从架构的角度来看,它带来了两个效率低下的问题:(1)数据传输带来的开销(2)ssd内部DRAM带来的能源效率低下。首先,在cache miss的情况下,目标数据需要经过DDR4模块(如内存控制器和DDR4 PHY)和PCIe模块(根复杂、事务层、数据链路层和物理层)。DDR4[59]的峰值带宽为每通道20gb/s,而ull-flash(包括大多数NVMe SSD产品)使用的PCIe 3.0为4 lanes,使得NVMe的最大带宽为4gb/s。因此,在缓存丢失的情况下,HAMS的性能会被峰值PCIe带宽所限制。此外,需要对NVDIMM的原始数据进行编码封装到PCIe包中,这也使得在缓存丢失的情况下,HAMS的延迟时间更长。

图10a显示了在执行从Section III中选择的工作负载时,数据移动延迟在平均内存访问时间(AMAT)中所占的比例。可以观察到,NVMe控制器和DDR4控制器之间移动数据所产生的接口延迟占总AMAT的39%,这会降低HAMS的性能。HAMS基线设计的另一个缺点是,即使HAMS已经将数据保存在NVDIMM中,数据仍然会被复制到ssd内部的DRAM中。虽然这将提高块存储用例下的性能(使用文件系统),但它也将引入额外的能源消耗,并增加SSD的内部复杂性。请注意,与由32个闪存芯片组成的闪存组合相比,ssd内部DRAM需要多17%的功率。

为了解决这些挑战,我们建议移除用于数据缓冲的SSD内DRAM,引入一个新的基于寄存器的接口(而不是门铃寄存器和PCIe bar),并连接ull-flash到DRAM PHY(而不是PCIe)。注意,写入到ull-flash已经减少,而不使用ssd内部DRAM,因为传入的数据是由NVDIMM缓冲/缓存的。同样地,地址映射表也缓冲在NVDIMM中。访问映射信息只消耗一个tCL和少量的tBURST周期(小于20ns),这与长时间的ull-flash访问延迟相比是可以忽略的。如图10b所示,这种NVDIMM和ull-flash的积极集成,我们称之为高级HAMS,允许NVMe控制器通过DRAM接口直接访问DRAM模块。具体来说,为了与同步DDR4接口兼容,NVMe控制器通过使用一组寄存器来缓冲命令、地址和数据,从而避免了底层Z-NAND访问的不可预知的延迟。对于通信,地址管理器使用SSD命令生成逻辑,根据HAMS需要发起的I/O请求,写入一组捕获源地址和目标地址以及I/O命令的寄存器。NVMe控制器从NVDIMM的源地址获取(或拉取)目标数据(通过DRAM接口写入地址寄存器),然后将其转发到flash固件,以便将其编程到flash媒体中。

在从HAMS控制器分配多个DDR4通道来连接每对DDR4通道的同时,NVDIMM和ull-flash可以并行处理MMU操作和ull-flash读写访问,这种设计也使得DDR4通道得不到充分利用。为了避免通道资源的浪费,我们建议将ull-flash和一个/多个nvdimm通过同一DDR4总线连接到HAMS控制器。然而,一个关键的设计问题是,在我们的设计中,NVDIMM可以同时被HAMS控制器和NVMe控制器访问。为了避免这两者同时进行访问,这种积极的集成还引入了一个锁寄存器,这表明NVMe控制器正在访问DDR4和NVDIMM进行数据传输。

5. 实现细节

5.A NVDIMM缓存和总线集成

HAMS地址管理:基于SRAM的MoS tag array会给HAMS控制器带来很大的电路面积成本,并在停电时增加元数据持久性的问题。相反,我们将MoS的NVDIMM cache配置为直接映射,并将其标签信息与ECC位集成到每条NVDIMM cacheline中,类似于Intel Knights Landing处理器[58]的MCDRAM配置。图11显示了NVDIMM缓存中MoS标签阵列的详细信息。MoS标签数组的每一个条目都包含了缓存的所有元数据,如标签、忙碌位(B)、有效位(V)和脏位(D)。当有内存请求进入时,它的地址被分解为标签、索引和偏移量字段。然后,HAMS地址管理器使用分解后的索引从NVDIMM缓存中检索标签数组项和数据块。比较器从检索的标记数组条目中提取存储的标记,并将其与相应内存请求的标记进行比较。如果两个标签匹配,则可以直接从HAMS控制器获取数据。另一方面,如果这两个标记不匹配,HAMS就会组成两个NVMe命令,一个用于读取,将数据从ull-flash填充到NVDIMM缓存条目,另一个用于写入,将数据从NVDIMM逐出到ull-flash。一旦目标数据在NVDIMM缓存中可用,HAMS就把它放在系统总线上,并通过设置MMU的命令和地址总线通知CPU完成。

基于寄存器的接口:图12说明了我们的高级HAMS控制器如何通过DDR4与底层NVMe控制器通信。在我们的设计中,为了向NVMe控制器发送I/O请求,HAMS控制器首先通过将其频闪器切换到高电压来取消NVDIMM的选择。在下一个时钟周期中,HAMS控制器通过将DDR通道中的WE#、CAS#和RAS#开关分别切换到低、低和高电压来配置写命令。在写入命令之后,I/O请求被封装为一个64B NVMe命令,在8周期数据突发中通过D[63:0]频闪传输到ull-flash的数据缓冲区寄存器。NVMe控制器然后从数据缓冲区寄存器中提取并解析请求信息(例如,请求类型、源/目的地址和数据长度),这与大多数NVMe ssd类似。需要注意的是,地址A[15:0]在HAMS控制器和NVDIMM控制器之间通信时不传递任何信息。

在处理NVMe写命令或基于NVMe读命令从flash介质获取数据的给定周期后,HAMS将锁寄存器设置为1,这表明NVMe控制器可以作为总线主控制器接管控制。如果配置了锁寄存器,NVMe控制器会根据DDR4接口的时序顺序初始化ull-flash与NVDIMM之间的DMA过程。在传输数据之后,NVMe控制器通过将锁寄存器重置为0来释放锁寄存器。HAMS缓存逻辑使用锁寄存器进行NVDIMM访问,避免了NVMe控制器和内存控制器同时使用总线的情况。

5.B NVMe和风险管理

每个NVMe队列条目的I/O请求可以通过填充NVMe命令结构的信息字段简单地组成。HAMS写入给定请求(读/写)的opcode字段,并将NVDIMM地址、SSD地址和页面大小(4KB)分别填充到相应的PRP、LBA和length字段中。生成的NVMe命令由HAMS NVMe引擎在SQ中排队。这个引擎编写门铃来通知ull-flash有一个请求。每当从HAMS的ULLFlash控制器下发中断时,NVMe引擎同步相应的CQ,并清除CQ和SQ的目标项。

有两个与NVMe管理相关的问题,因为NVDIMM被用作缓存和PRP目标:(1)驱逐风险和(2)冗余驱逐。当NVMe控制器和HAMS缓存逻辑访问相同的NVDIMM位置时,就会出现驱逐风险;而冗余退出则出现在缓存逻辑生成逐出命令时,该命令已经发出。考虑图13所示的示例。MMU请求读取MoS地址空间的0xf0,其中索引为0x0,标签为0xf。由于发生cache miss, HAMS缓存逻辑将页面(0xE0)逐出到ULLFlash,并请求在0xf0读取数据。同时,MMU访问0xf0来更新数据。这使得缓存逻辑再次逐出相同的数据,因为被逐出的请求仍然由ull-flash提供服务(即,冗余逐出)。现在,HAMS NVMe引擎包含三个NVMe命令(CMD1/2/3)。这些命令由NVMe控制器根据NVMe规范以FIFO顺序处理。然而,由于ssd内部任务,ULL-Flash中的I/O完成可能会乱序。更重要的是,NVMe控制器会根据完成顺序将数据传输到NVDIMM,这可能会导致驱逐风险。

为了防止这些危险和多余的驱逐,HAMS采用了两种技术。当NVMe引擎发出命令时,HAMS通过相应的NVDIMM克隆相应的页面缓存条目的PRP(在固定内存池分配)(图9)来隔离目标内容,然后更新PRP的值与克隆页面的位置,这样底层NVMe控制器不会在DMA中使数据不一致。此外,我们在固定内存中添加了一个等待队列,并使HAMS总是指向MoS tag array的一个繁忙位(参见第IV-B节)。当NVMe引擎完成请求时,HAMS缓存逻辑将位设置为1,然后将其重置为0。图14显示了一个示例,说明了如何处理驱逐危险和冗余驱逐问题。当缓存丢失发生时(从0x0e读取),缓存逻辑切换目标标记数组条目的繁忙位,并将目标页复制到PRP池条目。在此过程中,HAMS用PRP池条目替换对PRP的引用,并将其提交给NVMe引擎。在下一次缓存失败时(写入到0xf0),缓存逻辑意识到条目处于逐出过程中,并将请求放入等待队列。NVMe命令的I/O服务完成后,繁忙位将被清除,等待队列中的请求将再次发出。这样就避免了等待队列和繁忙位的退出风险和冗余退出问题。

5.C 断电下的持久性控制

如果将HAMS作为工作内存扩展,结合NVDIMM和ULLFlash扩展地址空间,目标系统将获得更大的内存空间。然而,它需要保证数据的持久性,因为MoS地址空间被认为是一个持久的内存扩展。因此,每当HAMS的缓存逻辑需要在ull-flash中更新数据时,就需要刷新NVMe请求。为了解决这个缺点,我们利用NVMe命令格式中的保留区域,在每个SQ的NVMe命令条目中添加一个日志标签。此日志标记保存指示相应请求是否由ull-flash完成的信息。每当NVMe引擎向ull-flash发送请求时,它都会将标记设置为1。一旦中断到达,HAMS就清除与I/O完成相关的标记。

图15给出了一个示例,说明了HAMS如何利用日志标记信息。在本例的第一阶段,HAMS将SQ中的所有命令发送给ULLFlash, cmd1、cmd3和cmd4被处理为引用SQ/CQ中相同位置的尾指针和头指针,这将清除相应的日志标记为0。在第一阶段结束时电源故障,ull-flash和HAMS无法完成cmd2。在我们的设计中,由于NVDIMM的固定内存空间保存了SQ区域的数据,因此HAMS首先在开机时检查SQ区域,以确定是否有任何命令的日志标签为1。如果有,那么在第二阶段,HAMS将拉动命令并为I/O服务创建一对SQ和CQ。然后,HAMS将其恢复到SQ,增加SQ的尾部指针,并按门铃登记,以便在停电时发出的未处理请求可以得到正确服务。

6. 评估

7. 相关工作和讨论

最近,英特尔发布了一个字节寻址的基于RAM的NVDIMM(即Optane DC PMM)来替代主存[27]。然而,与DRAM不同的是,用户应用程序不能在没有定制软件堆栈的情况下,使用加载/存储指令直接从提议的硬件访问持久数据。具体来说,操作系统需要一系列英特尔自定义的软件支持,包括块驱动程序、支持持久化内存的文件系统和直接访问(例如:将Optane DC PMM(作为内存)直接映射到用户空间。现有的应用程序还需要修改以与构建在DAX上的Intel运行时库[28]兼容。此外,从硬件设计的角度来看,Optane DC PMM也有一些缺点。具体来说,它的存储容量远远低于基于ull-flash的HAMS(即512 GB/DIMM vs. 2.3 TB/DIMM)[19]。在每个标准单位大小的内存包数量相同的情况下,Optane DC PMM的聚合吞吐量为4.5×lower,而ull-flash[29]的聚合吞吐量为[70]。它还面临着解决长PRAM写延迟问题的挑战。[66]报告说,Optane DC PMM集成了一个16KB XPBuffer来容纳写请求。然而,由于XPBuffer的大小是固定的且相对较小,[29]观察到,在写密集型的工作负载中,NVDIMM-N的性能比Optane DC PMM(作为持久内存)高出5.72倍。

之前的一些研究[17],[30],[42],[51],[62]提出将DRAM和flash集成到单个系统存储器中。类似于Optane DC PMM,内存请求需要经过多个软件层,包括NVML库和特定的HybriDIMM驱动[52],然后才能访问来自HybriDIMM的数据。另外,当将HybriDIMM配置为持久内存时,其内部的DRAM缓冲区是禁用的,这将直接向系统[50]暴露长flash延迟。

Abulila等人提出了FlatFlash[1],它利用NAND闪存来扩展内存空间。具体来说,FlatFlash通过利用SSD内部DRAM作为缓存,直接将ULL-Flash作为一个字节寻址设备暴露给主机。但是SSD内部DRAM的很大一部分被用来存储地址转换表[69]。剩余的DRAM空间比主机端DRAM小得多,可能不足以容纳整个工作集。此外,由于FlatFlash使用MMIO而不是NVMe协议来访问底层的ull-flash,因此它不能从SSD内部的并行性中获益,从而表现出较低的设备级吞吐量。虽然将热页迁移到主机端内存可以提高整体性能,但在这种情况下,FlatFlash不能保证数据的持久性。

相比之下,我们的HAMS扩展了主存的容量,而不需要修改传统的文件系统或用户应用程序。具体来说,就像DRAM一样,它直接将ULL-Flash的地址空间暴露给MMU,同时利用我们的HAMS控制器来管理NVDIMM和ULL-Flash之间的数据移动,使其对操作系统透明。据我们所知,这样的架构设计在以前的文献中没有讨论过。虽然HAMS也可以作为内核模块实现,但它要求操作系统响应NVDIMM中的每一个缓存丢失(即页面错误),这导致了上下文切换和页面错误处理的开销。当大型工作集导致NVDIMM和ull-flash之间频繁的页面交换时,这种软件开销是不可取的(参见图7a)。此外,通过最大化NVDIMM和ull-flash的吞吐量,HAMS优于其他DRAM+NVM方法(参见VI-B节)。我们的持久化控制设计还可以在不牺牲ull-flash性能的情况下保证数据的持久性。

一组先前的工作提出了分解内存解决方案,以扩展内存容量[36],[39],[44],[53]。例如,[53]探索了通过以太网构建跨1000个服务器的大型内存池的可行性。然而,这种设计存在网络带宽低和总拥有成本(TCO)高的问题。[44]部分地解决了上述的挑战。[44]通过使用PCIe接口提高网络吞吐量,通过在定制刀片服务器上部署更多DRAM内存,降低硬件基础设施成本。遗憾的是,由于DRAM内存的高成本(即价格和功耗),采用这种设计仍然具有挑战性。[36]通过用NAND闪存替换DRAM进一步降低TCO。但是,从远程服务器访问flash时,I/O延迟将增加10 ~ 15 us,比ZNAND的访问延迟(3us)高出5×longer。另一方面,[36]需要对正在运行的应用程序进行源代码级的修改,这向用户暴露了巨大的开销。与上述解决方案不同的是,HAMS是一种规模扩大的解决方案,它将本地NVDIMM和ull-flash的容量聚集成一个单一的内存空间。因此,HAMS节省了建造许多刀片服务器和购买昂贵的DRAM内存的巨大成本。此外,由于HAMS以一种透明的方式构建TB级的持久内存,因此在HAMS中执行应用程序不需要改变现有的编程模型。