这个问题与菲奥(灵活的 i/o 测试器)实用程序在使用引擎的同时管理 NVME 存储(特别是 SSD)的 I/O 队列libaio
。
为了测试我正在使用Ubuntu 14.04 和商用 NVMe SSD。
我使用以下参数执行 fio 实验:
direct=1
numjobs=256
iodepth=1
ioengine=libaio
group_reporting
对于此示例,假设 nvme 设备通告/支持10 IO队列创建的最大队列深度为 64。您可以假设在初始化过程中 10 个队列创建成功。
根据以上参数和约束,
"How would fio use the queues, for I/O commands?"
或者缩小范围,"Does the iodepth argument in fio directly equate to nvme_queue_depth for the test"
这就是问题所在。
我期望类似下面这样的事情会发生,但没有正确的信息。
示例场景 1:
fio 是否生成 256 个作业/线程,这些作业/线程尝试将 i/o 提交到 nvme_queues,并尝试在任何时候在 10 个 nvme_queues 中保留至少 1 个 i/o cmd。如果作业发现队列已满(即,如果 nvme_queue 中存在(一个)i/o cmd,则尝试在其他 9 个 nvme_queues 中提交,或者可能循环,直到找到一个空队列)示例场景 2:
fio 256 个线程/作业,实际上并不尊重用于此测试的 iodepth==nvme_quedepth,并且无论如何都会提交多个 i/o。因此,例如,每个线程只向 nvme_queues 提交 1 个 i/o cmd,而不检查 10 个 nvme_queues 中的命令深度。换句话说,256 个线程尝试在 10 个 nvme_queues 中维持大约 25 或 26 个 i/o 待处理/进行中。
链接至定义深度来自 fio 文档。
这两种情况都是真的吗?有没有办法通过实验来确定。
通过 nvme 和 fio 的规范并没有真正清楚地说明如何处理这种情况,或者是模糊的。
更新:以下是图像格式的两种场景 https://i.stack.imgur.com/4tGcm.jpg(无法嵌入)顶部是场景 1,底部是 scn。2
更新 2:如果问题比较模糊,请见谅,但我会尝试通过进一步扩展来改进它。
我的理解是,设备和 fio 之间。因此,问题涉及这里涉及的多层代码和/或协议。列出它们
1. Fio(应用程序)和 libaio
2. Linux 内核/操作系统
3. Nvme 驱动程序
4. 存储设备 SSD 控制器和代码。
上面解释的两种情况只是试图在非常高的层次上进行模糊的解释以回答我自己的问题,因为我到目前为止还不是上述层面的专家。
根据下面的回答,这似乎scenario 1
与主题不太相关。想多了解一点有关一般政策和所有层面的可预测性的信息。部分解释可以,希望可以结合成一个完整的解释。
因此,这个问题的第三个天真的表述是 "how does fio issue traffic and how they really end up the storage nvme_queues?"
答案1
TLDR;从用户空间 I/O 提交到 I/O 离开内核的设计在Linux Block IO:在多核系统上引入多队列 SSD 访问纸。
"How would fio use the queues, for I/O commands?"
或者缩小范围"Does the iodepth argument in fio directly equate to nvme_queue_depth for the test"
这种想法有点也wooly,我会对此提出警告。“fio 将如何使用队列来执行 I/O 命令?”——不仅仅是 fio。“fio 中的 iodepth 参数是否直接等同于测试中的 nvme_queue_depth”——可能但可能不是?在您的示例中,fio 将 I/O 提交给内核,但内核反过来可能会选择在将该 I/O 提交到磁盘之前对其进行转换(请参阅此回答“fio 测试中的 iodepth 到底是什么意思?它是队列深度吗?”)。
场景 1:fio 是否生成 256 个作业/线程,这些作业/线程尝试将 i/o 提交到 nvme_queues,并尝试在任何时候在 10 个 nvme_queues 中保留至少 1 个 i/o cmd
有点(但 s/jobs/processes/)。每个作业(如果示例完整,则可能映射到进程)最多向内核提交一个 I/O。但是请记住,fio 对您的磁盘可以做什么一无所知,并且取决于您的内核选择如何安排其 I/O 和每个单独的 fio 进程。
示例场景 2
恐怕我不明白,因为您没有给出单独的例子。iodepth
在这种情况下,“ ”是指 fio 的iodepth
参数吗?
这两种情况都是真的吗?
我不明白您的场景 2 和场景 1 会产生很多开销,而且我们不知道内核会对 I/O 做什么,所以我认为这无法得到明确的答案(例如,我有点怀疑您的 NVMe 磁盘出现了 SCSI 设备节点......)。
我建议查看iostat
fio 作业运行时的内容以获得一些想法,但对每个作业执行一次 I/O 是一种非常低效的提交 I/O 的方式,并且会产生大量开销(这可能会阻止您达到最佳速度)。通常,您会安排作业提交尽可能多的 I/O,然后才引入其他作业。
更新
根据您在更新中包含的图表,我们或多或少处于您认为的场景 2(256 个进程,每个进程提交一个 I/O,NVMe 磁盘有多个队列,每个队列都有单独的深度,而不是一个巨大的队列),但想象一下从用户空间进入内核的漏斗和从内核到“磁盘”队列的另一个(不同的)漏斗(让我们忽略 HW RAID 等),而不是某种从用户空间进程到磁盘队列的一对一映射。除非您对磁盘使用用户空间驱动程序,否则您将无法控制给定 I/O 最终进入哪个队列,因为内核会为您抽象该决定。例如,您的进程可能会跨 CPU 运行(由内核决定),并且您甚至可能在同一物理 CPU 上拥有不平衡的进程数量(与其他 CPU 上的数量相比),这进一步混淆了情况。
并希望多了解一点有关各层级的总体政策和可预测性
您可能需要跟踪内核块层来确定您正在使用的内核版本。此外,一些 Ubuntu 14.04 内核不支持多队列(请参阅此LWN 文章对 blk-mq 进行了简要概述)对于 NVMe 磁盘(我认为3.19 内核引入了对 NVMe 设备的 blk-mq 支持)这让人想起了我的“我有点怀疑您的 NVMe 磁盘是否与 SCSI 设备节点一起出现”的评论。有一篇论文叫做“Linux Block IO:在多核系统上引入多队列 SSD 访问“更详细地讨论了 blk-mq 的变化和好处,并涵盖了第 1-3 个方面。如果你想了解第 4 个方面的详细信息,你最好再问一个问题,但SSD 编码给出了初步总结。
fio 如何发出流量以及它们如何真正进入存储 nvme_queues?
取决于 I/O 引擎和您选择的配置 :-) 但是对于示例配置,您给出了图 2 和图 5“在多核系统上引入多队列 SSD 访问”论文封面下面发生了什么fio和“fio 测试中的 iodepth 到底是什么意思?它是队列深度吗?”答案涵盖在 fio 本身内。