【问题标题】:Is a CPU core busy while reading from persistent storage?从持久存储读取时 CPU 内核是否忙?
【发布时间】:2017-10-27 11:22:29
【问题描述】:

一般来说,当一个进程线程进行读取系统调用时,线程的执行被挂起并且读取本身发生(或计划发生)在操作系统内核中。读取完成后,内核会安排暂停的线程继续执行。这部分我明白了。

我的问题是,当内核从持久性存储(例如 HDD 或 SSD)读取时,是否有 CPU 内核忙于编排读取?

我要求帮助确定我的进程中的最佳线程数。例如,如果我有一个 4 核 CPU,并且我的进程中的一个线程在读取系统调用时阻塞,那么在等待读取完成时,还有多少其他线程可以并行运行? 3? 4?在 3 和 4 之间有更微妙的东西吗?

【问题讨论】:

  • HDD 存储的典型延迟约为 ...gist.github.com/jboner/2841832 10 毫秒或 30000000 CPU 滴答声; SSD 更快,大约 1-0.5 毫秒或大约 1500000-3000000(在 3 GHz CPU - 3 个滴答/纳秒,3000 个/我们,300 万个/毫秒)。因此,当文件读取错过了已经缓存在内存中的文件数据并产生外部 I/O 读取时,CPU 可能不会忙于等待请求并允许其他线程运行。
  • 不要尝试确定线程数,而是使用非阻塞调用。

标签: multithreading file io multiprocessing


【解决方案1】:

HDD 存储的典型延迟约为 ... https://gist.github.com/jboner/2841832 每个程序员都应该知道的延迟数字 生的

Read 4K randomly from SSD*             150,000   ns      150 us          ~1GB/sec SSD
Read 1 MB sequentially from SSD*     1,000,000   ns    1,000 us    1 ms  ~1GB/sec SSD, 4X memory
Disk seek                           10,000,000   ns   10,000 us   10 ms  20x datacenter roundtrip
Read 1 MB sequentially from disk    20,000,000   ns   20,000 us   20 ms  80x memory, 20X SSD
  • 对于 HDD 10 毫秒或 30000000 CPU 滴答声;
  • 对于更快的 SSD:大约 1-0.5 毫秒或大约 1500000-3000000(在 3 GHz CPU - 3 个滴答/纳秒,3000 个/我们,300 万个/毫秒)。

因此,当文件读取未命中已缓存在内存中的文件数据并生成外部 I/O 读取时,CPU 可能不会忙于等待请求并允许其他线程运行。 CPU 将用于通过 VFS 子系统和 I/O 驱动程序生成 I/O 请求。并且完成的请求将(在典型情况下)产生中断,以通知驱动程序所需的数据已加载到内存中。

【讨论】:

    【解决方案2】:

    不,读取不会使 CPU 内核保持忙碌。

    以下是对尝试从驱动器读取时发生的情况的(非常)简化的描述:

    • 应用程序要求操作系统读取。
    • 如果从文件中读取:文件系统检查其缓存。如果请求的数据在缓存中,则立即返回。如果不是,则文件系统要求存储驱动程序从驱动器中获取数据。请参阅下一步。
    • 存储驱动程序向存储设备(例如硬盘驱动器)发送请求以获取数据。然后,驱动器会异步处理此请求。
    • 操作系统使应用程序进入睡眠状态(更准确地说:等待读取的线程)。
    • ...一段时间过去了...
    • 存储设备已完成读取请求的数据。它引发了一个中断。
    • 调用操作系统/驱动程序的中断处理程序,将数据复制到应用程序的内存中。
    • 应用程序的阻塞线程已解除阻塞并计划执行。
    • 应用程序的线程继续运行。

    从这里可以看出,任何地方都没有忙碌的等待。当应用程序被阻塞等待读取时,CPU 可以用于其他任务(如果没有其他任务,则进入空闲状态)。

    编辑:正如评论中提到的osgx,这有例外。网络和存储层,至少在 Linux 中,在某些情况下会使用忙轮询,此时阻塞比异步继续要快。

    【讨论】:

    • 使用网络驱动程序时,有时会出现临时的无中断忙等待模式:NAPI polling (sometimes with low-latency)。对于 80、120 或 200 IOPS 的 SATA/SAS HDD,不需要这种模式,但对于超过 10000 IOPS 的现代 SSD,驱动程序中也应该有轮询模式(每秒 10000 次中断是一个很大的数字,而 SATA/SAS 为 90k或 NVMe 的 150000 更大)。
    • @osgx 感谢您提供此附加信息。我已将此添加到我的答案中。
    • Rolf,对于某些网络和may be true for some NVMe SSDs (blk_mq_poll/io_poll_delay),轮询是正确的,但仅限于系统范围的视图。对于单进程来说,单次请求不会在很短的轮询时间内完成,它会一直休眠直到中断。只有当有许多进程和许多请求时,轮询模式可能有助于通过跳过中断进入/退出或上下文切换来降低平均延迟。
    • 如果发生这种情况,CPU 内核会忙于旋转一段时间,对吧?你有什么建议我应该如何改写答案的那部分?
    • 答案已经正确。刚刚了解 Linux 中的 NVMe 轮询。带轮询的快速 NVMe 设备也有助于处理单个请求 - slide 10,14 events.linuxfoundation.org/sites/events/files/slides/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-12
    • 2014-04-02
    • 1970-01-01
    • 2013-03-21
    相关资源
    最近更新 更多