2010-11-01 72 views
14

我想知道是否有办法连接unix文本文件在一起更快 比运行cat什么是捕捉多个文件的最快方法?

这是我面临的问题。我正在处理一个文本文件〜100G的字符串,大小为 。我试图通过将文件分成几百个小文件并并行处理它们来改善运行时间。最后,我将所得到的 文件依次整理在一起。文件读/写时间本身需要几个小时。我 会想找到一种方法,以改善以下:

cat file1 file2 file3 ... fileN >> newBigFile 
  1. 这就需要双倍的磁盘空间为file1 ... fileN占据了100G,并 然后newBigFile另需100Gb的,然后file1。 .. fileN得到 去除

  2. 的数据已经在file1 ... fileN,做cat >>即被读 ,写的时候我真正需要的是为几百个文件到 重新出现1个文件...

+0

。 – 2010-11-01 19:31:11

+0

我不知道我在说什么,但有可能操纵文件记录或什么?由于我需要做的不是复制数据,而是将多个文件串在一起回到1? – Wing 2010-11-01 19:37:52

回答

4

快,但不是免费的解决方案?获取SSD驱动器或基于闪存PCIe的存储。如果这是必须定期完成的事情,那么提高磁盘IO速度将是您可以获得的最具成本效益和最快的加速。

+0

谢谢,但不幸的是,我无法更改公司的文件服务器和硬件...... – Wing 2010-11-01 19:34:17

+2

当然,您的情况可能会禁止此操作,但如果它作为现有服务器磁盘存储(而不是替代品)的附加功能呈现给管理层,可以考虑。如果您可以拥有仅用于此任务的SSD,并且每天可以节省2小时的处理时间,我认为他们会相信节省的成本。 – 2010-11-01 21:25:54

4

也许dd会更快,因为您不必在cat和shell之间传递内容。喜欢的东西:

mv file1 newBigFile 
dd if=file2 of=newBigFile seek=$(stat -c %s newBigFile) 
+1

我绝对认为dd与删除文件一起复制为Robie Basak所建议的文件,将会构成最重组的解决方案,而不是使用mmap实现自定义cp/unlink命令。然而,我相信没有什么比完全消除分裂更有效率。 – frankc 2010-11-01 21:59:06

1

我真正需要的是对数百个文件,再度出山担任1个文件...

的原因,它是不实际的刚刚加入的文件这样的文件系统因为文本文件通常不会精确地填充磁盘块,所以后续文件中的数据将不得不向上移动以填补空白,导致一堆读取/写入无论如何

4

是否可以简单地不分割文件?通过在每个并行工作者中设置文件指针,而不是通过块来处理文件。如果文件需要以面向行的方式进行处理,这会使其更加棘手,但仍然可以完成。每个工作人员都需要理解这一点,而不是从你给出的偏移量开始,它必须首先逐字节地寻找下一个新行+1。每个工作人员还必须明白,它不会处理您设置的字节数量,但必须在分配给它处理的设置字节量之后处理第一个换行符。

文件指针的实际分配和设置非常简单。如果有n个工人,则每个人处理n /文件大小字节,并且文件指针从工人编号* n/file_size开始。

是否有某种原因,这种计划是不够的?

+0

而不是修改工作人员,shell可以为工作人员提供一个“stdin”,它已经只是它应该工作的部分,例如使用sed来选择一个行范围。如果需要协调输出,GNU Parallel可以为此提供帮助。 – 2010-11-01 21:28:41

+0

这整个事情都是在perl中完成的,原始脚本试图通过整个100G文件串行地进行字符串操作。现在我已经分裂了文件并通过fork()处理块,但是现在读/写时间瓶颈了运行时。我不需要像你说的那样进行初始分割,但是我仍然必须写出已处理的块,然后将它们放回到一个文件中,对吧? – Wing 2010-11-01 21:54:31

+0

如果我没有拆分文件并让每个子进程读取在不同行上工作的原始100G文件,我是否会遇到尝试读取同一文件的200个进程的瓶颈? – Wing 2010-11-01 22:00:09

6

当文件串联到一起,你可以删除小文件,因为他们得到附加:

for file in file1 file2 file3 ... fileN; do 
    cat "$file" >> bigFile && rm "$file" 
done 

这将避免需要双倍的空间。

没有其他方式神奇地使文件神奇连接。文件系统API根本没有这样的功能。

6

如果您不需要随机访问最终的大文件(即从头到尾只读一遍),则可以让数百个中间文件显示为一个。在这里你通常会做

$ consume big-file.txt 

,而不是做

$ consume <(cat file1 file2 ... fileN) 

它使用Unix的process substitution,有时也被称为 “匿名命名管道”。

您还可以通过拆分输入和同时进行处理来节省时间和空间; GNU Parallel有一个--pipe switch这将做到这一点。它还可以将输出重新组合为一个大文件,可能使用较少的暂存空间,因为它只需要一次性将个数个磁盘保留在磁盘上。如果您真正在同时运行数百个进程,Parallel可以让您调整并行机器的数量,从而大大提高效率。我强烈推荐它。

+0

我还没有测试过这个,但它听起来像是最有用的建议 – Michael 2012-02-22 14:56:13

+0

流程替换看起来很棒,因为它不会把东西放在磁盘上。所以你可以做“消耗<(cmd1 file1)<(cmd2 file2)<(cmd3 file3)”。但是,这里相当于更传统的“cat file1 file2 ... | consume”。 – dfrankow 2012-05-18 21:30:00

1

有太多的并发性。

这样做的一个更好的方法是在所需范围内使用对文件的随机读取读取,并且不会实际将其分割并仅将文件数量作为机器中物理CPU /内核的数量进行处理。那除非是用IOPS淹没磁盘,那么你应该削减,直到磁盘不是瓶颈。

你正在做的事情是产生大量的IOPS,而且它没有办法解决它的物理问题。

2

我相信这是最快的方式猫都包含在同一文件夹中的文件:这听起来像你应该使用一些具有比Unix外壳多一点肌肉

$ ls [path to folder] | while read p; do cat $p; done 
+0

不错=)这工作桃色。需要回声;在完成之前。 – Kieveli 2017-07-06 18:11:18

相关问题