是否可以从多个线程写入同一文件的不同部分?

Posted

技术标签:

【中文标题】是否可以从多个线程写入同一文件的不同部分?【英文标题】:Is is possible to write to different parts of the same file from multiple threads? 【发布时间】:2013-03-06 20:30:25 【问题描述】:

我可以从多个线程(在典型的 PC 上)同时写入同一文件的不同部分吗?我的意思是只有一个磁头,所以写入只能以某种顺序执行,即不能并行,对吧?

编辑:

我正在编写一个对大型二进制文件进行排序的程序,但大部分时间仍然花在磁盘 I/O 上,所以我只是想知道通过并行 I/O 是否会获得额外的速度。

【问题讨论】:

是的,这应该是可能的,这就是 utorrent 软件的工作原理..!! 您说的是物理并行性?如果您谈论物理并行性 - 想想它如何与单核处理器一起工作。 它不会解决你的 IO 问题。如果您最终需要从不同线程写入同一个文件以解决 CPU 绑定限制,它会起作用,但不会提高您的 IO 速度。如果有的话,它会稍微减少。 【参考方案1】:

没有什么可以阻止您让多个线程写入同一文件的不同部分。

我有一个对大型二进制文件进行排序的程序,但大部分时间仍然花在磁盘 I/O 上,所以我只是想知道通过并行执行 I/O 是否会获得额外的速度。

如果程序是磁盘绑定的,使其成为多线程(并且仍然将相同数量的数据写入同一个磁盘)不会加快它的速度。

如果我们谈论的是传统硬盘驱动器,顺序 I/O 通常比涉及来回移动磁盘磁头的 I/O 更快。考虑到这一点,跨线程拆分 I/O 甚至可能适得其反。

就加快速度而言,有多种途径可供探索:

    减少 I/O 量(例如,通过采用需要更少 I/O 的排序算法,或通过在内存中执行更多工作); 提高 I/O 吞吐量,例如使用更快的驱动器。

【讨论】:

【参考方案2】:

至少在 unix(-like) 操作系统上是可能的,大概在 Windows 上也是可能的,尽管文件处理有些不同,可能需要特定的文件模式允许这样做(编辑:参见 answer of bizzehdee 了解详细信息)。

在运行的操作系统上,“文件”实际上是一个逻辑实体,它的某些状态在任何给定时间都存储到磁盘中,但也有一些变化仅在内核缓冲区中。因此,在某种程度上,写入文件与写入共享内存块没有什么不同,只是 API 不同(即使使用 mmap 也不一样)。

但简而言之,只要查找和写入,文件中的旧字节就会被覆盖。如果两个进程在相同的字节上重叠写入,我认为最终结果是未定义的,并且在任何情况下都不应该在正常运行的系统中发生,并且任何这样做的程序都应该有一些机制来防止重叠写入。


关于加速:真的取决于你做什么。如果您只执行原始写入,传统旋转硬盘的速度可能会变慢,或者文件可能更容易碎片化。在 SSD 上,可能没有减速,但也没有加速。

另一方面,如果您的操作是 CPU 密集型的,并且您有多个内核,并且并行处理可以让您获得更高的总 CPU 使用率,那么并行处理同一输出文件的不同部分可以加快速度事情,如果与写入文件的字节相比有很多处理,甚至很多。

【讨论】:

【参考方案3】:

您需要查看CreateFileExWriteFileEx 并使用lpOverlapped。这允许在多个线程中同时异步读取和/或写入同一文件。

http://msdn.microsoft.com/en-us/library/windows/desktop/aa365748(v=vs.85).aspx

【讨论】:

【参考方案4】:

是的,这是可能的,但正如其他人所说,在一般情况下,不太可能提高性能。

但是,您的其中一个陈述并不正确。

只有一个磁头

首先,通常每个表面都有一个,因此即使是单盘 HDD 也会有两个磁头。当然,多盘的有更多。

一些具有多个盘片的驱动器也能够同时读取或写入所有盘片。 80 年代的一些Fujitsu Eagle drives 做到了这一点,并被用于第一批能够记录未压缩数字视频信号的系统。当然,这不是“随机访问”,因为所有头都一起移动。我不确定现代驱动器是否使用这种技术。

【讨论】:

以上是关于是否可以从多个线程写入同一文件的不同部分?的主要内容,如果未能解决你的问题,请参考以下文章

使用来自多个进程的 fseek/fwrite 写入文件的不同区域?

Java并发编程教程

从多个线程写入内存区域会导致争用吗?

多线程文件写同一个文件写不进去

对于写入固定大小数组的不同部分的并行线程,是不是存在线程安全的 Java 数据结构?

是否可以读取同一线程最后写入的值? [复制]