【发布时间】:2017-01-29 20:28:26
【问题描述】:
我有一个遗留项目,它从 STDIN 获取大量数据并在 perl 脚本中逐行处理。行顺序并不重要。 这需要很长时间,所以我想并行进行。
经过一番研究,我发现Parallel::Loops 看起来很合适,但我无法让它工作,因为$_ 是空的。我的代码是:
#Initialize all vars etc
$pl->while ( sub { <STDIN> }, sub {
print $_ # but $_ is empty
}
其他从 STDIN ir 并行读取的方式也很受欢迎。
更新:
在获得所有帮助后,我可以管理一些工作代码,谢谢。我要做一个简短的摘要。澄清一下:
这是一种解析器,它有 3000 多行正则表达式和 自动生成的条件。
我用于测试的输入是一个 POS 标记的文本,这个文件有 1071406 行。
我的硬件是:SSD 磁盘、中档 i5 上一代和 8gb RAM DDR4。
结论:
- 因为 cmets 建议 IO 操作使我的脚本变慢。
- 所有建议都带来了改进,特别是包括处理成串行而不是逐行处理的建议。
- 答案包含对未来工作非常有用的线程实现。
- Framework Parallel::ForkManager 在执行时间上引入了很多延迟。我总是在 5 分钟后终止脚本,因为没有并行性的脚本大约需要 6 分钟。
- Framework Parallel::Loops 引入了一些改进。该脚本大约需要 3 分钟才能完成。
- 使用 GNU 并行是一种简单的优化方法。
- 使用 Threads 包我得到了最好的时间,1 分 45 秒,但它非常接近 GNU 并行,所以你可以尝试一下,并努力移植代码。
- 使用@ikegami 答案中的线程包读取一堆行,时间与应用@tanktalus 解决方案的时间相同,逐行读取。
最后,我将使用@ikegami 解决方案,我认为当数据量增加时会更好。例如,我将要处理的行数调整为 100.000,因为它比 10.000 获得更好的结果。这种差异大约是 8 秒。
下一个自然步骤是将所有内容写入文件而不是使用 STDOUT,我希望这有助于进一步减少时间。
【问题讨论】:
-
保持您的代码不变并将其包装在 GNU Parallel 中也许...
cat hugeData | parallel --pipe ./existingScript.pl。或者 shebang-wrap 你现有的脚本...gnu.org/software/parallel/parallel_tutorial.html#Shebang -
cat hugeData |最好替换为<hugeData -
@MarkSetchell 谢谢。但是时间比按原样运行脚本要差一些。
-
好的,希望值得一试。我想时间主要是 I/O 而不是计算,所以并行处理不会有太大帮助。
-
@MarkSetchell 是的,看来你是对的。稍后我将尝试带全文的脚本,这需要 1 周才能完成。也许在那里我们可以看到差异。
标签: perl while-loop parallel-processing