本文介绍了如何通过优化 NVMe 驱动器和 AMD EPYC 9005 系列处理器的配置,实现 4900 万 IOPS 和 340 GB/s 带宽的性能优化。文章详细分析了性能优化最佳实践、FIO 基准测试设置及结果,并给出了相关建议,以帮助读者在实际系统中实现最佳性能。这些优化措施包括事务数量、待处理的中断数量、NPS、内存带宽、中断合并、并发任务数量、硬件同步多线程(SMT)感知、非一致性内存访问(NUMA)感知、首选I/O和宽松排序等。此外,文章还展示了使用 FIO 在配备 24 个三星 PM1743 NVMe 驱动器的 128 核 AMD EPYC 系统上进行的测试结果,包括随机读写和顺序读写的扩展性测试,以及测试结果的图表。
文章介绍了针对 NVMe 驱动器和 AMD EPYC 9005 系列处理器的性能优化最佳实践,包括事务数量、待处理的中断数量、NPS、内存带宽、中断合并、并发任务数量、硬件同步多线程(SMT)感知、非一致性内存访问(NUMA)感知、首选I/O和宽松排序等优化措施。
文章讨论了 FIO 基准测试的设置,包括被测系统配置、FIO 安装及调优注意事项、擦除、预处理、测试策略、核心/CCD绑定与操作系统任务调度器、内存带宽、中断合并、并发任务数量、硬件同步多线程(SMT)感知、非一致性内存访问(NUMA)感知等。
文章展示了使用 FIO 在配备 24 个三星 PM1743 NVMe 驱动器的 128 核 AMD EPYC 系统上进行的测试结果,包括随机读写和顺序读写的扩展性测试,以及测试结果的图表。
目录
通过优化 NVMe 驱动器和 AMD EPYC 9005 系列处理器的配置,实现了 4900 万 IOPS 和 340 GB/s 带宽。详细分析了性能优化最佳实践、FIO 基准测试设置及结果,希望能帮助读者在实际系统中实现最佳性能。
本文主要内容翻译自《NVMe®
Tuning Guide for AMD EPYC™ 9005 Series Processors》,原始资料链接见文末。
第一章:引言
1.1 - NVMe
NVMe
是一种用于通过
PCIe
总线访问非易失性存储介质的开放式逻辑设备接口。在本文发布之时,市场上已有一些
PCIe Gen5 NVMe
驱动器,但大多数
NVMe
驱动器的速度为
Gen3
(
8 GT/s
)和
Gen4
(
16 GT/s
)。第五代(
32 GT/s
)
NVMe
驱动器因更低的
I/O
开销、更低的延迟以及对多个长命令队列的支持而提升了性能。
NVMe
驱动器的优势如下:
-
性能
:减少延迟,增加顺序访问的带宽以及随机访问的
IOPS
。
-
高密度
:可在
PCIe Switch
后配置多个
NVMe
驱动器。
-
速度
:可使用
PCIe Gen3
(
8 GT/s
)、
PCIe Gen4
(
16 GT/s
)或
PCIe Gen5
(
32 GT/s
)的
NVMe
驱动器。
-
以下性能指标对
NVMe
驱动器十分重要:
NVMe
默认必须处理两种类型的数据:每次读取(
IOP
)对应一个完成信号和一个中断,并且按顺序处理。
每个
PCIe
写入事务的典型最大写入块大小为
256 B
。
NVMe
读取操作是指向系统内存的
PCIe
写入事务。如今市面上较好的
PCIe Gen5 NVMe
驱动器在采用
PCIe x4
格式时,最多可处理大约
1800 KIOPS
的随机读取。一个
16
通道的
PCIe
端口可以连接四个
x4 NVMe
驱动器,如果驱动器采用
x8
规格,则可连接两个。
本调优指南通过讨论第五代
AMD EPYC
处理器所提供的
NVMe
子系统的选择及选项,以及各选项的权衡取舍,来帮助您解决这些瓶颈问题。
1.2 - 工作负载概述
FIO
是一种用于对不同类型的
I/O
进行综合基准测试的工具。
FIO
支持许多
I/O
引擎,例如
sync
、
mmap
、
libaio
、
posixaio
、
SG v3
、
splice
、
null
、
network
、
syslet
、
guasi
、
solarisaio
等,支持多线程任务、带宽限制以及指定
I/O
优先级的功能。它支持典型的工作负载类型,如顺序读取、顺序写入、随机读取和随机写入。顺序操作衡量带宽,随机操作衡量每秒输入
/
输出操作次数(
IOPS
)。如需更多信息,请参阅
FIO文档
(
https://buildmedia.readthedocs.org/media/pdf/fio/latest/fio.pdf
)。
FIO
基准测试使用顺序访问来衡量以
KBps
为单位的带宽吞吐量性能,并使用
IOPS
来衡量随机访问
I/O
性能。与
NVMe
设备规格中公布的最大吞吐量相比,使用随机读取和写入操作能让
FIO
避开内置的预取逻辑,从而对设备延迟提供更贴合实际的测量结果。伪随机线性反馈移位寄存器(
LFSR
)引擎用于生成均匀随机分布。随机工作负载使用
4 KB
的块大小,而顺序工作负载使用
128 KB
的块大小。
numactl
是可选的,因为
FIO
已经有
“
--cpus_allowed
”
参数可将线程绑定到逻辑核心上。
PCIe
协议是另一个可能影响
NVMe
性能的因素。
PCIe
通道数量会限制进行顺序读写时的最大理论带宽,并且通常与供应商在
NVMe
驱动器规格中所报告的最大带宽一致。表
1-1
展示了
PCIe
单向最大理论带宽。
表
1-1
:
PCIe
单向最大理论带宽
本调优指南针对配备最新
BIOS
引导程序、采用
AMD EPYC 9005
系列处理器的单插槽或双插槽系统。这些系统应包含一个或多个未挂载为活动目录的
PCIe Gen3
、
Gen4
或
Gen5 NVMe
设备。为保持一致性,请将最新的
FIO
构建为静态二进制文件,首选
PCIe
第五代
NVMe
设备。
1.3 - 重点阅读
请务必阅读以下指南(可从
AMD 文档中心获取
https://www.amd.com/en/search/documentation/hub.html
),这些指南包含了有关第五代
AMD EPYC
处理器的重要基础信息:
• AMD EPYC™ 9005 Processor Architecture
Overview
• BIOS & Workload Tuning Guide for AMD EPYC™ 9005 Series Processors《
AMD
EPYC 9005服务器BIOS & 工作负载调优指南
》
• Memory Population
Guidelines for AMD EPYC™ 9005 Series Processors
第二章:性能优化最佳实践
AMD EPYC 9005
系列处理器包含诸如
AMD Infinity Fabric
等技术,可解决在使用
NVMe
驱动器时出现的以下瓶颈问题:
-
每秒必须处理的事务数量。
-
每秒必须处理的中断数量。
-
使用队列深度为
1
时固有的事务序列化等待问题。
这些瓶颈在所有系统中都存在,但每个瓶颈出现的具体节点有所不同。
2.1 - 事务数量
AMD EPYC
处理器通常能够在事务准备好处理时同时处理多个并发事务。在使用严格的
PCIe
排序时,较新的已提交写入操作会因较旧的已提交写入操作的发布而被阻塞,即便较新操作与较旧操作之间并无任何依赖关系。严格排序意味着较新的写入操作在较旧的写入操作发布之前无法发布,这意味着无法充分发挥
AMD EPYC
处理器的优势。
2.1.1 -
建议的优化方法
PCIe
允许放松已提交写入操作的顺序。如果较新的已提交写入操作与较旧的已提交写入操作之间没有依赖关系,并且写入的位置不同,那么较新的已提交写入操作可以在较旧的已提交写入操作之前或与其同时发布。这使得在任何给定时间都能够处理多个事务。
NVMe
事务包含两种不同的已提交写入操作:数据事务和完成事务。
AMD
建议使用多个
NVMe
驱动器,而不是相对于先前写入操作放松完成事务的顺序,因为这可能会破坏生产者
-
消费者模型。
2.2 - 待处理的中断数量
第五代
AMD EPYC
处理器提供了一个集中式中断和异常处理单元,该单元可减少路由开销并有助于扩展,从而在核心数量较多时为处理能力带来显著优势。
AMD Infinity Fabric
旨在向处理程序每秒提供多达
150
万个中断,且不会影响性能。将中断数量保持在此阈值以下可显著提升性能。
以下参数在优化中断处理方面可发挥重要作用:
-
NVMe feature ID
设置。
-
更高的核心数量。
-
轮询模式(
Polling mode
)。
2.2.1 - NVMe Feature ID
设置
设备会发出中断以指示任务已完成。默认情况下,
NVMe
控制器会为从队列中处理的每个命令发出一个完成信号。
NVMe
控制器可设置为在发出单个完成信号及相应中断之前,指定可合并的完成信号数量。进行此操作时,请务必设置不少于
100 μs
的超时时间,以防完成信号无法合并。例如,在处理
10
个任务后发出一个完成信号,可使用以下命令:
nvme set-feature
/dev/nvme0n1<
磁盘地址
> --feature-id 8 –value 522
注意:必须对每个
NVMe
设备都执行此操作。
在流量较低的情况下,
NVMe feature-ID
设置存在一些缺点。例如,使用队列深度为
1
意味着设备不会有
10
个完成信号可合并,并且会等待
100 ms
的超时时间,这会降低性能。
AMD
建议在使用此优化方法时将队列深度至少设置为
16
。
2.2.2 -
更高的核心数量
增加可处理由计划任务或线程数量所控制的事务的处理器核心数量,是中断处理的另一项推荐优化方法。
AMD
建议每个
NVMe
驱动器使用四到八个核心。将核心、内存和设备置于同一插槽可提升性能。以下是将核心、内存和设备分配到同一插槽的示例:
numactl --membind=1 --cpunodebind=0-3 --numjobs=1 --iodepth=64
--group_reporting --runtime=600
2.2.3 - Polling Mode
一些较新的
NVMe
驱动器支持使用轮询模式,在这种模式下,内核驱动程序会轮询完成队列,而不是等待中断来处理它们。如果设备驱动程序支持轮询模式,那么
NVMe
完成操作可以基于轮询而非基于中断。如果内核支持,您可以为每个队列指定连续、自适应混合或固定时间混合轮询,以便在该队列的延迟、吞吐量和
CPU
使用率之间实现平衡。轮询(即使是混合轮询)比中断会占用稍多的
CPU
资源。要在内核中设置轮询模式,可使用以下命令:
echo 1 >
/sys/block/
/
/io_poll
要设置不同的轮询参数:
-
连续轮询:
echo -1 >
/sys/block/
/
/io_poll_delay
-
自适应混合轮询:
echo 0 > /sys/block/
/
/io_poll_delay
-
固定时间混合轮询:
echo
> /sys/block/
/
/io_poll_delay
2.3 - NPS
AMD
建议在
BIOS
中将
L3 Cache as NUMA
选项启用,并将
NPS
设置为
1
。
第三章:FIO 性能基准测试设置
本章介绍了用于本调优指南的被测系统(
SUT
)详细信息、测试方法以及平台配置。被测系统针对连接到由
128
核(
256
线程)
AMD 9005
系列处理器驱动的双插槽系统的
NVMe
驱动器执行
I/O
性能测试。基于
Linux
的
FIO
工具在不同配置下被用于执行和分析这些性能测试。
3.1 - 被测系统配置
表
3-1
展示了用于测试
24
个
x4
系列
NVMe
固态硬盘(
SSD
)性能的被测系统配置。
组件
|
详情
|
操作系统
|
Ubuntu 22.04
|
Node per Socket(NPS)
|
1
|
处理器
|
2 个 128 核的第五代 AMD EPYC
|
核心
|
每个 CPU 128 个
|
线程
|
每个 CPU 256 个(启用同步多线程技术,SMT 打开时)
|
SSD驱动器
|
最多 24 个 NVMe
PCIe Gen5。
有关本章所述测试所用配置的信息,请参阅第 27 页的
“
术语表
”
。
|
FIO 版本
|
3.28
|
表
3-1
:被测系统配置
3.2 - FIO 基准测试安装及调优注意事项
大多数
Linux
发行版都包含预编译的
FIO
软件包,这意味着在测试前您无需下载并编译源代码。然而,
AMD
为了在各被测系统间保持功能的一致性和完整性,使用了静态构建的
FIO
版本。
要在基于
Ubuntu 22.04
的发行版上安装系统自带的预编译
FIO
(版本
3.28
,
注:可能已有更新版本
),可使用以下命令:
# sudo apt install fio
要在基于
RHEL8/CentOS8
的发行版上安装系统自带的预编译
FIO
(版本
3.7
),请使用以下命令:
# sudo dnf install fio
要在
Ubuntu 22.04
系统上静态下载并构建最新的
FIO
,可按以下步骤操作:
# sudo apt install libaio-dev libbsd-dev di
valgrind libtcmalloc-minimal4 libcunit1 libcunit1-dev libgfapi0 libiscsi-dev
nvme-cli numactl
# git clone https://github.com/axboe/fio
# cd fio
# git checkout fio-3.28
(
或酌情用更新版本替代
)
# ./configure --build-static --enable-lex
# make
# sudo make install
注意事项
:
3.2.1 -
擦除(
Purging
)
擦除操作可将固态硬盘设备恢复到一种状态,使得后续的写入操作尽可能如同设备从未被使用过且不包含任何有效数据时那样执行。要在
Linux
中执行此任务,需安装
nvme-cli
软件包,它提供了基本的
nvme
命令。如果安装了合适的
nvme-cli
软件包,那么可以执行以下命令来安全擦除整个驱动器。例如,要擦除
nvme1n1
驱动器,可使用以下命令:
# nvme format /dev/nvme1n1 --ses=1
(
编者注:
请注意格式化等操作的风险,被测试的
SSD
不要包含任何有用的数据。本文后续将不再提示
)
-
默认的
“
--ses=0”
选项表示不请求安全擦除操作。
-
设置
“
--ses=1
”
会触发安全擦除模式,该模式会擦除用户数据,并可能用
0
或
1
替换数据。
-
设置
“
--ses=2
”
会执行速度较慢但更安全的加密用户数据擦除操作,然后删除加密密钥。
以下是一个使用
“
--ses=1
”
擦除后的驱动器示例:
# hexdump -n 16 /dev/nvme1n1
0000000 0000 0000 0000 0000 0000 0000 0000 0000
0000010...
请务必在安全擦除后对驱动器进行预处理。这是因为
AMD EPYC
数据架构会对连续的
00h
数据返回进行优化,从而导致吞吐量过高,远超
NVMe
设备规格所规定的值。
3.2.2 -
预处理(
Preconditioning
)
全新的设备或处于类似状态的设备通常在过渡到与实际工作负载性能相对应的稳定状态之前,会有一段性能提升期。设备必须处于
“
稳定状态
”
才能进行准确的测量。稳定状态由以
“
轮次
”
衡量的窗口定义,当测试结果进入并保持稳定状态至少五轮时,即视为达到稳定状态。存储网络行业协会(
SNIA
)指南规定,当相邻两次运行之间的变化小于
20%
时,即达到稳定状态。《
使用
SNIA
固态硬盘性能测试规范理解固态硬盘性能
》(
https://www.snia.org/sites/default/files/UnderstandingSSDPerformance.Jan12.web_.pdf
)解释了固态硬盘预处理的重要性。
对
NVMe
驱动器进行预处理可使其进入稳定状态,因此这是获得可重复且具有代表性的测试结果的最重要要求。按照
固态存储(
SSS
)性能测试规范(
PTS
)企业版
1.0
(
https://www.snia.org/sites/default/files/technical-work/pts/release/SNIA-SSS-PTS-Enterprise-v1.0.pdf
)对
NVMe
驱动器进行预处理。有两种可接受的预处理类型:
AMD
推荐这种方法,即使用顺序
128 KB
块写入两倍用户容量的数据。
以下是一个预处理命令示例:
# dd if=/dev/random of=/dev/nvme1n1 bs=128k
status=progress
3.2.3 - NVMe Gen5
测试策略
NVMe
的性能与
CPU
核心分配直接相关。有时候,让
Linux
内核任务调度器来确定最佳分配方式是最为简便的做法。内存带宽会直接影响
NVMe
第五代驱动器的最大
IOPS
以及性能。
AMD
建议填满所有内存通道以实现最大带宽。此外,物理
CPU
核心能够处理的
IOPS
比其同步多线程(
SMT
)伙伴核心更多。
本调优指南中所述的测试是按照
第
2
页的
“
工作负载概述
”
来执行的。
3.3 - 测试方法
测试是依照
第
2
页的
“
工作负载概述
”
来进行的。
3.4 - 核心 /
CCD绑定与操作系统任务调度器
NVMe
性能与
CPU
核心分配直接相关。
Linux
内核任务调度器会确定最佳分配方式,但
AMD
的测试中很少看到超过
5%
的性能提升。一些测试表明,当绑定到
CCD
或
CPU
核心时,性能会下降
5%
。您还应该考虑物理核心与
SMT
核心的相对能力,因为物理核心能够处理的
IOPS
比其
SMT
核心更多。
3.5 - 内存带宽
当接近
PCIe
带宽限制时,要留意内存带宽限制情况。
AMD
建议填满所有内存通道以获取最大内存带宽。
3.6 - 中断合并
中断合并能够降低
CPU
的中断开销。请参阅《
NVM Express®
基础规范
》(
https://nvmexpress.org/wp-content/uploads/NVM-Express-Base-Specification-2.0b-2021.12.18-Ratified.pdf
)的第
5.27.1.6
节内容。
3.7 - 并发任务数量(numjobs)
为了在
PCIe Gen5 U.2 “
供应商
A”
驱动器上实现最大
IOPS
,必须对
FIO
应用程序进行配置,使其使用多个
Zen 5
核心。
3.8 - 硬件同步多线程(SMT)感知
要特别留意
SMT
和非一致性内存访问(
NUMA
)设置。每个
NVMe PCIe
设备都与一个
NUMA
节点相关联,在
BIOS
中将节点
NPS
设置为
4
,并将
ACPI
SRAT L3 Cache As NUMA Domain
设置为启用状态后,就能显示出这些关联关系。将
FIO
进程绑定到错误的核心或
NUMA Node
上,可能会导致无法实现最大
IOPS
或带宽。
AMD EPYC Zen 5 CPU
缓存架构允许每个核心访问其自身的一级(
L1
)和二级(
L2
)缓存。每个核心复合体芯片(
CCD
)包含
8
个核心,这
8
个核心(以及它们的
SMT
伙伴核心)共享同一个三级(
L3
)缓存的访问权限。
lstopo
是一个
Linux
实用工具,它能够帮助我们了解
CPU
核心和
SMT
兄弟核心,以及主机系统缓存架构的相关情况,例如:
这个示例表明,核心
P0
和核心
P192
是
SMT
兄弟核心,它们与核心
P1