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

Posted

技术标签:

【中文标题】使用来自多个进程的 fseek/fwrite 写入文件的不同区域?【英文标题】:Using fseek/fwrite from multiple processes to write to different areas of a file? 【发布时间】:2012-05-12 18:25:58 【问题描述】:

我最近遇到了一些未经充分测试的遗留代码,用于将分布在多个进程(这些是基于 MPI 的并行计算的一部分)的数据写入同一个文件。这真的可以保证工作吗?

是这样的:

所有进程打开同一个文件进行写入。

每个进程调用fseek 来寻找文件中的不同位置。该位置可能超出文件末尾。

然后每个进程将一个数据块写入带有fwrite 的文件中。寻找位置 和块大小使得这些写入完全平铺 文件的部分——没有间隙,没有重叠。

这能保证有效吗,还是有时会严重失败?没有锁定来序列化写入,实际上它们很可能是从同步点开始的。另一方面,我们可以保证他们正在写入不同的文件位置,这与其他在尝试从多个进程写入“文件末尾”时遇到问题的问题不同。

我突然想到,这些进程可能位于通过 NFS 挂载文件的不同机器上,我怀疑这可能回答了我的问题——但是,如果文件是本地的,它会工作吗?

【问题讨论】:

操作系统是否允许打开多个文件句柄以在同一个文件上写入?有什么理由需要它们是同一个文件而不是以后拼凑在一起吗? 理论上,如果没有两个或更多进程尝试写入文件末尾,则它应该可以工作,即如果您预先分配了所有必要的空间,则所有写入都应该成功。我不确定如果两个进程尝试写入 EOF 并且文件被扩展(并且新创建的空间用零填充)会发生什么。 我使用 HDF5/MPIO 来处理此类任务,HDF5 对于维度数据非常有用,并且提供了简单的并行访问。 【参考方案1】:

我相信这通常会起作用,但不能保证我能找到。 fwrite(3) 的 Posix 规范遵循 ISO C,并且两个标准都没有提到并发性。

所以我怀疑它通常会起作用,但 fseek(3) 和 fwrite(3) 是缓冲 I/O 函数,因此成功将取决于库实现的内部细节。因此,绝对没有保证,但有各种理由期望它会起作用。

现在,如果程序使用 lseek(2) 和 write(2) 那么我相信你可以考虑保证结果,但现在它仅限于 Posix 操作系统。

有一点似乎……很奇怪……为什么MPI 程序 决定通过NFS 而不是消息API 来共享它的数据?它看起来更慢、更不便携、更容易出问题,而且通常只是浪费 MPI 功能集。鉴于对单个 NFS 服务器的依赖,它肯定不再是分布式的。

【讨论】:

程序可能希望将其分布式数据(例如分散在进程中的大型矩阵)写入非易失性存储。这是 HPC 中的一种常见操作,MPI 标准为此提供了自己的并行 I/O API。 最近我对一个文件进行了解锁/非同步、并行write()ing,使用多个线程,到文件的非重叠部分,包括在 EOF 之外寻找,没有任何问题。跨度> 谢谢! FWIW,我认为您的最后一段可能是现实世界的正确问题——这是一些遗留库功能,因为六年前有人认为用户可能想要它。在“不保证”和“这是一件很奇怪的事情”之间,我认为如何处理代码的答案是显而易见的,即使它可能有效......

以上是关于使用来自多个进程的 fseek/fwrite 写入文件的不同区域?的主要内容,如果未能解决你的问题,请参考以下文章

从 PM 或 VFS 服务器 (Minix) 写入文件

来自管道的多个固定大小记录的读取器

在将输出写入文件时使用多处理显示来自子进程的实时输出

使用来自 Python 的 1 个进程使用 HDF5 和 MPI 写入/读取大文件

多个线程同时写入多个文件 - 它正被另一个进程使用

通过管道从多个子进程写入父进程