为什么这个特定Perl脚本的线程版本比非线程脚本慢200倍?

时间:2009-11-07 03:06:16

标签: perl multithreading

来自2003 Perl会议的presentation Mikhael Goikhman包括一对素数查找脚本的示例。 One是线程化的,other不是。在运行脚本(打印行注释掉)后,我在非线程版本上的执行时间为0.011秒,在线程版本上的执行时间为2.343(!)秒。是什么导致了时间的惊人差异?

我对Perl中的线程有一些经验并且之前已经注意到线程创建时间可能特别残酷,但这似乎不是Goikham示例中的瓶颈。

4 个答案:

答案 0 :(得分:15)

Jay P.是对的:

~$ strace -c ./threads.pl
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 99.80    0.116007       10546        11           futex
  0.20    0.000229           6        36           mmap2
  0.00    0.000000           0        31           read
  0.00    0.000000           0        49        13 open
  0.00    0.000000           0        36           close

将其与:

进行比较
~$ strace -c ./no-threads.pl
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 90.62    0.000261         261         1           execve
  9.38    0.000027           0       167           write
  0.00    0.000000           0        12           read
  0.00    0.000000           0        38        13 open
  0.00    0.000000           0        25           close

答案 1 :(得分:12)

我是一个Python人,而不是Perl,所以我对代码的作用只有一个模糊的概念。但是,当您看到队列时,请务必小心。 Python有一个线程安全的队列,看起来像Perl也是如此。它们非常棒,因为它们可以为您提供线程安全性,但它们通常涉及很多昂贵的锁定和解锁队列,这可能是您所有时间的所在。

答案 2 :(得分:7)

你有多少个处理器?通常,当线程数>时,任何计算密集型任务都会变慢。处理器数量。这是因为在线程之间切换是很昂贵的(“上下文切换”)。上下文切换涉及停止1个线程,保存其上下文,然后将另一个线程的上下文放入处理器中,以便它可以运行。一切都是为了什么?因此,线程A可以计算12321是否可以被7整除而不是线程B?

如果你有2个触发器,我敢打赌,2个线程的版本可能是最快的,4个触发器 - &gt;使用4个线程等<​​/ p>

答案 3 :(得分:2)

这是一个病态案例。真正的答案是:在开始使用Perl ithreads之前,您需要了解一些有用的方法。众所周知,它们在某些方面(共享数据)效率低,而在其他方面则很好(它们是并发的)。

如果您将子线程执行的工作块与将数据从一个线程发送到另一个线程的次数相比会增加很多,那么事情就会大不相同。

与像Jay P这样的Python线程相比:正如他所说的那样,Python线程是合作的,只在一个核心上运行。 Perl的ithreads非常不同。它们可以在每个核心上运行,但是能够这样做是因为每个线程基本上有一个单独的解释器。这使得线程之间的通信类似于进程间通信,包括相关的开销。