当我使用线程时,为什么我的Perl脚本会慢速解压缩文件?

时间:2009-11-09 14:48:50

标签: performance perl multithreading

所以我在使用线程支持编译的核心2 duo macbook pro上运行perl 5.10:usethreads=defineuseithreads=define。我有一个简单的脚本来读取4个gzip文件,每个文件包含750000行。我正在使用Compress::Zlib来解压缩和读取文件。我有2个实现,它们之间的唯一区别是包含use threads。除此之外,两个脚本都运行相同的子程序来进行读取。因此,在伪代码中,非线程程序执行此操作:

read_gzipped(file1);
read_gzipped(file2);
read_gzipped(file3);
read_gzipped(file4);

线程版本如下:

my thr0 = threads->new(\$read_gzipped,'file1')
my thr1 = threads->new(\$read_gzipped,'file1')
my thr2 = threads->new(\$read_gzipped,'file1')
my thr3 = threads->new(\$read_gzipped,'file1')

thr0->join()
thr1->join()
thr2->join()
thr3->join()

现在,线程版本的运行速度几乎比非线程脚本快2倍。这显然不是我希望的结果。谁能解释我在这里做错了什么?

4 个答案:

答案 0 :(得分:10)

你正在使用线程来尝试加速IO绑定的东西,而不是CPU绑定的东西。这只会引入更多的IO争用,这会减慢脚本速度。

答案 1 :(得分:9)

我的猜测是GZIP操作的瓶颈是磁盘访问。如果您有四个线程在platter硬盘上竞争磁盘访问,那么这会大大减慢速度。磁盘头必须快速连续移动到不同的文件。如果您一次只处理一个文件,则磁头可以保持在该文件附近,并且磁盘缓存将更准确。

答案 2 :(得分:4)

如果你正在处理大部分 cpu绑定的东西,那么ithreads工作得很好。解压缩是cpu绑定的。

使用Parallel::ForkManager模块可以轻松解决问题。

通常 - Perl中的线程并不是很好。

答案 3 :(得分:0)

我不准备假设您在运行时没有看到top的输出而受到I / O限制。和depesz一样,我倾向于认为压缩/解压缩操作(数学上很重)更容易受CPU限制。

当您处理CPU绑定操作时,使用比处理器更多的线程/进程几乎永远不会 [1]改善问题 - 如果CPU利用率已经达到100%,更多线程/进程不会神奇地增加其容量 - 并且最有可能通过增加更多的上下文切换开销来使事情变得更糟。

[1]我听说它建议重建编译,例如构建新内核,可以告诉make使用两倍于机器有处理器的进程,我的个人经验就是这个似乎是准确的。我听到的解释是,这允许每个CPU在一个进程中忙于编译,而另一个进程正在等待从主存储器中提取数据。如果将编译视为受CPU限制的进程,则这是普通规则的例外。如果您将其视为I / O绑定的情况(I / O位于CPU和主内存之间而不是磁盘/网络/用户I / O),则不是。