15

我正在使用 Python 多处理为每个进程生成一个临时输出文件。它们的大小可以是几 GB,我做了几十个。这些临时文件需要连接以形成所需的输出,这是被证明是瓶颈(和并行性杀手)的步骤。是否有一个 Linux 工具可以通过修改文件系统元数据而不是实际复制内容来创建连接文件?只要它适用于我可以接受的任何 Linux 系统。但是文件系统特定的解决方案不会有太大帮助。

我没有受过操作系统或 CS 培训,但从理论上讲,似乎应该可以创建一个新的 inode 并从我要复制的文件的 inode 中复制 inode 指针结构,然后取消链接这些 inode。是否有任何实用程序可以做到这一点?考虑到经过深思熟虑的 unix 实用程序过多,我完全期望它会如此,但找不到任何东西。因此,我对 SO 的问题。文件系统位于块设备上,实际上是硬盘,以防此信息很重要。我没有信心自己写这篇文章,因为我以前从未做过任何系统级编程,所以任何指针(指向 C/Python 代码片段)都会非常有帮助。

4

6 回答 6

15

即使有这样的工具,这也只有在保证除最后一个文件之外的文件的大小是文件系统块大小的倍数的情况下才有效。

如果您控制数据写入临时文件的方式,并且您知道 每个文件的大小,则可以改为执行以下操作

  1. 在开始多处理之前,创建最终输出文件,并通过 fseek()ing 到最后将其增长到最终大小,这将创建一个 稀疏文件

  2. 开始多处理,将 FD 和偏移量交给每个进程到文件的特定切片中。

这样,这些进程将协作填充单个输出文件,无需稍后将它们组合在一起。

编辑

如果您无法预测单个文件的大小,但最终文件的使用者可以使用顺序(而不是随机访问)输入,您可以cat tmpfile1 .. tmpfileN在标准输入上提供给使用者

cat tmpfile1 ... tmpfileN | consumer

或通过命名管道(使用 bash 的 Process Substitution):

consumer <(cat tmpfile1 ... tmpfileN)
于 2011-05-05T06:39:42.007 回答
5

您表示您事先不知道每个临时文件的大小。考虑到这一点,我认为最好的办法是编写一个FUSE文件系统,将块呈现为单个大文件,同时将它们作为单独的文件保存在底层文件系统上。

在此解决方案中,您的生产和消费应用程序保持不变。生产者写出一堆文件,FUSE 层使它们显示为单个文件。然后将该虚拟文件呈现给消费者。

FUSE 绑定了多种语言,包括 Python。如果您在此处此处查看一些示例(这些示例用于不同的绑定),这需要非常少的代码。

于 2011-05-05T06:47:36.877 回答
3

4个文件;xaa、xab、xac、xad bash 中的快速连接(以 root 身份):

losetup -v -f xaa; losetup -v -f xab; losetup -v -f xac; losetup -v -f xad

(假设 loop0、loop1、loop2、loop3 是新设备文件的名称。)

http://pastebin.com/PtEDQH7G放入“join_us”脚本文件中。然后你可以像这样使用它:

./join_us /dev/loop{0..3}

然后(如果这个大文件是电影)您可以将其所有权授予普通用户(chown itsme /dev/mapper/joined),然后他/她可以通过以下方式播放它:mplayer /dev/mapper/joined

这些之后的清理(以root身份):

dmsetup remove joined; losetup -d /dev/loop[0123]
于 2013-09-18T08:52:57.570 回答
2

我不这么认为,inode 可能是对齐的,所以只有在你可以在一个文件的页脚和另一个文件的标题之间留下一些零(或未知字节)的情况下才有可能。

我建议不要连接这些文件,而是重新设计分析工具以支持从多个文件中进行采购。以日志文件为例,很多日志分析器支持每天读取日志文件。

编辑

@san:正如您所说,您无法控制正在使用的代码,您可以使用命名管道即时连接单独的文件:

$ mkfifo /tmp/cat
$ cat file1 file2 ... >/tmp/cat &
$ user_program /tmp/cat
...
$ rm /tmp/cat
于 2011-05-05T06:42:00.040 回答
0

不,没有这样的工具或系统调用。

您可能会调查每个进程是否可以直接写入最终文件。假设进程 1 写入字节 0-X,进程 2 写入 X-2X,依此类推。

于 2011-05-05T06:40:18.687 回答
0

一种可能的替代方法是将所有临时文件分类到命名管道中,然后使用该命名管道作为单输入程序的输入。只要您的单输入程序只是按顺序读取输入并且不查找。

于 2011-05-05T06:53:25.073 回答