Perl:并行或多线程或Bloom-Faster或fork来填充来自5亿行文件的哈希值

时间:2013-12-04 03:45:15

标签: perl

与并行运行一样,更快地完成此脚本的最佳解决方案是什么?

#!usr/bin/perl

use warnings;
use strict;
use threads;
open(R1 ,"<$ARGV[0]") || die " problem in oppening $ARGV[0]: $!\n";
my %dict1 : shared;
my $i=0;
while (my $l = <R1>){
     chomp($l);
     $l=~ s/\s$//;
     $l=~ s/^\s//;
     if ($l=~ /(.*)\s(.*)/){
          $i++;
          #print $1,"\n";
          #my $t = threads->create($dict1{$1}++);
          $dict1{$1}++;
     }
}
print $i, "\n";
close R1;

2 个答案:

答案 0 :(得分:1)

您可以创建与文件的相等部分对应的$N元素数组

my $N = 6;
my $step = int( $file_size/$N );
my @arr = map { ($_-1) * $step } 1 .. $N;

然后通过寻找文件位置(perldoc -f seek),读取行的其余部分(perldoc -f readline)并告知更正的文件位置(perldoc -f tell)来更正这些数字。

启动$N个线程,其中每个线程已经知道从哪里开始提取作业,并在最后加入他们的结果。然而,你可能会发现,媒体阅读是实际的瓶颈,正如@ikegami已经指出的那样。

答案 1 :(得分:0)

最可能的情况是,您受到从磁盘读取数据的速度(“I / O界限”)的限制,而不受处理时间(“CPU绑定”)的限制。如果是这种情况,那么你可以用线程或并行执行 nothing 来加快速度 - 如果它有任何影响,并行化会通过强制磁盘跳回来减慢你的速度在不同进程/线程读取的文件各部分之间。

测试是否是这种情况的简单方法是打开shell并运行命令cat my_data_file > /dev/null这应该告诉您从磁盘读取文件需要多长时间,而不实际做任何事情。如果它与在my_data_file上运行程序所需的时间大致相同,那么就不要费心去尝试优化或加速它了。你不能。在这种情况下,只有两种方法可以提高性能:

  1. 更改代码的工作方式,以便您无需读取整个文件。如果您正在处理将要运行多次的事情,那么在文件中索引记录或使用数据库可能有所帮助,但如果这是一次性操作(由于您仍然需要阅读整个文件一次创建索引/数据库)。

  2. 使用更快的存储媒体。

  3. 如果你没有受到I / O限制,那么下一个最可能的情况就是你的内存受限 - 数据不会一次全部适合内存,导致磁盘在将数据块移入数据库时​​发生颠簸并且没有虚拟内存。再次,并行化过程会使事情变得更糟,而不是更好。

    此案例中的解决方案与以前类似:

    1. 更改您正在执行的操作,以便您不需要同时在内存中存储所有数据。在这种情况下,即使是一次性操作,索引或数据库也可能是有益的。

    2. 购买更多内存。

    3. 除非你对数据进行更多的处理,而不是只使用几个正则表达式并将其填充到你已经显示的哈希值中,否则你肯定 CPU绑定并且并行化将会不提供任何好处。