多线程从磁盘读取

multithread read from disk?

本文关键字:读取 磁盘 多线程      更新时间:2023-10-16

假设我需要从保存在磁盘上的同一文件中读取许多不同的、独立的数据块。

可以多线程上传吗?

相关:同一处理器上的所有线程是否使用相同的IO设备从磁盘读取?在这种情况下,多线程根本不会加快上传速度——线程只是在排队等待。

(我目前正在使用OpenMP进行多线程处理。)

是的,这是可能的。但是:

同一处理器上的所有线程是否使用相同的IO设备从磁盘读取?

是。磁盘上的读取头。例如,尝试并行复制两个文件,而不是串行复制。这将需要更长的并行时间,因为操作系统使用调度算法来确保两个线程/进程之间的IO速率"公平"或相等。正因为如此,读取头将在磁盘的不同部分之间来回跳跃,从而大大减慢处理速度。与查找数据的时间相比,实际读取数据的时间非常短,而且当您同时读取磁盘的两个不同部分时,大部分时间都在查找。

请注意,所有这些都假设您使用的是硬盘如果你使用的是SSD,它在并行时不会更慢,但也不会更快Edit:根据评论,并行实际上对SSD来说更快。有了RAID,情况会变得更加复杂,而且(显然)取决于您使用的RAID类型。

这就是它的样子(我把圆盘展开成一个矩形,因为ascii圆很硬,并简化了数据布局,使其更容易阅读):

假设文件被盘片上的一些空间隔开,如下所示:

|         |

序列读取将看起来像(*表示读取)

space ----->
|        *|  t
|        *|  i
|        *|  m
|        *|  e
|        *|  |
|       / |  |
|     /   |  |
|   /     |  V
|  /      |
|*        |
|*        |
|*        |
|*        |

而并行读取看起来像

|        |
|        *|
|       / |
|     /   |
|   /     |
|  /      |
|*        |
|        |
|        |
|        |
|        |
|        *|
|       / |
|     /   |
|   /     |
|  /      |
|*        |
|        |
|        |
|        |
|        |
|        *|

etc

如果您在Windows上执行此操作,您可能需要研究ReadFileScatter函数。它将允许您在单个异步调用中读取文件中的多个段。这将允许操作系统更好地控制文件IO瓶颈,并有望优化读取。

Windows上匹配的写入调用将是WriteFileGather。

对于UNIX,您正在考虑readv和writev来做同样的事情。

如其他答案中所述,根据文件在磁盘上的物理存储方式,并行读取可能会较慢。因此,如果头部必须移动相当长的距离,可能会导致实际的减速。也就是说,存在可以有效地支持多个同时读取和写入的存储系统。我能想到的最简单的就是一个固态硬盘。我自己使用的是IBM的出色存储系统,它可以同时执行读写操作,而且速度不会减慢。因此,让我们假设您有这样一个文件系统和物理存储,它不会降低并行读取的速度。

在这种情况下,并行读取是非常合乎逻辑的。一般来说,有两种方法可以实现这一点:

  1. 如果您想使用标准的C/C++库来执行IO,那么您唯一的选择就是为每个线程保留一个打开的文件句柄(描述符)。这是因为文件指针(指向文件中的读写位置)是按句柄保存的。因此,如果你试图同时从同一个文件句柄中读取,你将无法知道你实际读取的内容
  2. 使用特定于平台的API来执行异步(OVERLAPPED)IO。在windows上,您使用WinAPI函数和所谓的OVERLAPPEDIO。在Unix/Linux上,您有posix AIO,尽管我知道不鼓励使用它,但我没有看到任何令人满意的解释来解释为什么会出现这种情况

我自己在linux和windows上都实现了fd/线程方法,在windows上实现了OVERLAPPED方法。两者都很好。

您将无法加快向磁盘读取的过程。如果你在写作的同时进行计算,那么并行化会有所帮助。但是,纯粹的写入将受到处理器和硬盘驱动器之间通道带宽的限制,更值得注意的是,受到硬盘驱动器本身的限制(我的硬盘驱动器有30MB/s,我听说过为120服务的突袭设置MB/s,但不要依赖于此)。

根据操作系统的设计,从磁盘进行多次读取应该是线程安全的。如果您使用标准的系统功能,则无需手动锁定,但以只读方式打开文件。(否则会出现文件访问错误。)

顺便说一句,如果你在实践中不需要从磁盘上读取,操作系统将决定从哪里为你提供服务。它通常从内存中预取读取和服务。