假设我需要从磁盘上保存的同一个文件中读取许多不同的、独立的数据块。
这个上传可以多线程吗?
相关:同一处理器上的所有线程是否使用相同的 IO 设备从磁盘读取?在这种情况下,多线程根本不会加快上传速度——线程只会排队等待。
(我目前正在使用 OpenMP 进行多线程处理。)
假设我需要从磁盘上保存的同一个文件中读取许多不同的、独立的数据块。
这个上传可以多线程吗?
相关:同一处理器上的所有线程是否使用相同的 IO 设备从磁盘读取?在这种情况下,多线程根本不会加快上传速度——线程只会排队等待。
(我目前正在使用 OpenMP 进行多线程处理。)
对的,这是可能的。然而:
同一处理器上的所有线程是否使用相同的 IO 设备从磁盘读取?
是的。磁盘上的读磁头。例如,尝试并行而不是串行复制两个文件。并行需要更长的时间,因为操作系统使用调度算法来确保两个线程/进程之间的 IO 速率是“公平的”或相等的。正因为如此,读磁头会在磁盘的不同部分之间来回跳跃,从而大大减慢了处理速度。与查找数据的时间相比,实际读取数据的时间非常短,而且当您一次读取磁盘的两个不同部分时,您大部分时间都在查找。
请注意,所有这些都假设您使用的是硬盘。如果您使用的是 SSD,并行运行速度不会变慢,但也不会变快。编辑:根据评论,SSD 的并行实际上更快。使用 RAID,情况会变得更加复杂,并且(显然)取决于您使用的 RAID 类型。
这就是它的样子(我将圆形磁盘展开成一个矩形,因为 ascii 圆圈很难,并简化了数据布局以使其更易于阅读):
假设文件被盘片上的一些空间分隔,如下所示:
| |
系列阅读看起来像(*
表示阅读)
space ----->
| *| t
| *| i
| *| m
| *| e
| *| |
| / | |
| / | |
| / | V
| / |
|* |
|* |
|* |
|* |
虽然并行读取看起来像
| \ |
| *|
| / |
| / |
| / |
| / |
|* |
| \ |
| \ |
| \ |
| \ |
| *|
| / |
| / |
| / |
| / |
|* |
| \ |
| \ |
| \ |
| \ |
| *|
ETC
如果您在 Windows 上执行此操作,您可能需要查看ReadFileScatter函数。它将允许您在单个异步调用中从文件中读取多个段。这将允许操作系统更好地控制文件 IO 瓶颈,并有望优化读取。
Windows 上匹配的写入调用将是WriteFileGather。
如其他答案中所述,并行读取可能会更慢,具体取决于文件物理存储在磁盘上的方式。因此,如果头部必须移动很长一段距离,则可能会导致实际减速。话虽如此,但有些存储系统可以有效地支持多个同时读取和写入。我能想象的最简单的是SSD磁盘。我本人曾使用 IBM 的出色存储系统,它可以同时执行读取和写入而不会减慢速度。因此,让我们假设您有这样一个文件系统和物理存储,在并行读取时不会减慢速度。
在这种情况下,并行读取是非常合乎逻辑的。一般来说,有两种方法可以实现:
我自己在 linux 和 windows 上实现了 fd/thread 方法,在 windows 上实现了 OVERLAPPED 方法。两者都工作得很好。
您将无法加快读取磁盘的过程。如果您在写作的同时进行计算,并行化会有所帮助。但是纯粹的写入将受到处理器和硬盘驱动器之间的通道带宽的限制,更值得注意的是,受到硬盘驱动器本身的限制(我的硬盘驱动器为 30 MB/s,我听说过 120 MB/s 以上的 raid 设置网络,但不要依赖它)。
如果您使用标准系统功能,则从磁盘进行多次读取应该是线程安全的,如果您使用标准系统功能,则无需手动锁定它,但以只读方式打开文件。(否则你会得到文件访问错误。)
顺便说一句,您实际上不需要从磁盘读取,操作系统将决定它从哪里为您服务。它通常从内存中预取读取和服务。