Python多进程与多线程在Windows和Linux上进行CPU绑定工作的比较

33
我写了一些测试代码,来看看在CPU密集型工作方面,多进程模块与线程相比的性能表现。在Linux上,我得到了预期的性能提升:
linux (dual quad core xeon):
serialrun took 1192.319 ms
parallelrun took 346.727 ms
threadedrun took 2108.172 ms
我的双核MacBook Pro也表现出同样的行为:
osx (dual core macbook pro)
serialrun took 2026.995 ms
parallelrun took 1288.723 ms
threadedrun took 5314.822 ms
然后我尝试在Windows机器上运行,得到了非常不同的结果。
windows (i7 920):
serialrun took 1043.000 ms
parallelrun took 3237.000 ms
threadedrun took 2343.000 ms
为什么多进程方法在Windows上如此缓慢呢?
以下是测试代码:

3
我在一台四核的戴尔PowerEdge 840服务器上运行了你的测试代码,操作系统为Win2K3。结果并不像你的那么惊人,但是你的论点仍然有效:串行运行花费了1266.000毫秒 并行运行花费了1906.000毫秒 线程运行花费了4359.000毫秒我很感兴趣看到你得到的答案,我自己也不知道。 - Jeff
5个回答

27

Python multiprocessing文档指出Windows中缺少os.fork()导致出现的问题。这可能适用于此处。

尝试导入psyco,观察会发生什么。首先,使用easy_install安装:

C:\Users\hughdbrown>\Python26\scripts\easy_install.exe psyco
Searching for psyco
Best match: psyco 1.6
Adding psyco 1.6 to easy-install.pth file

Using c:\python26\lib\site-packages
Processing dependencies for psyco
Finished processing dependencies for psyco

将以下代码添加到您的Python脚本的顶部:

import psyco
psyco.full()

我没有做任何处理,就得到了以下结果:

serialrun took 1191.000 ms
parallelrun took 3738.000 ms
threadedrun took 2728.000 ms

我使用以下代码获得这些结果:

serialrun took 43.000 ms
parallelrun took 3650.000 ms
threadedrun took 265.000 ms

并行仍然较慢,但其他方法速度非常快。

编辑:另外,尝试使用多进程池。(这是我第一次尝试,速度非常快,我想我一定漏掉了什么。)

@print_timing
def parallelpoolrun(reps):
    pool = multiprocessing.Pool(processes=4)
    result = pool.apply_async(counter, (reps,))

结果:

C:\Users\hughdbrown\Documents\python\StackOverflow>python  1289813.py
serialrun took 57.000 ms
parallelrun took 3716.000 ms
parallelpoolrun took 128.000 ms
threadedrun took 58.000 ms

非常整洁! 降低迭代(进程)数量,同时提高计数值表明,正如拜伦所说,并行缓慢是由于Windows进程的额外设置时间造成的。 - manghole
进程池似乎不会等待自己完成,虽然有一个join()方法可供进程池使用,但它似乎并没有像我想的那样起作用:P。 - manghole

25

UNIX变种中的进程要轻量得多。Windows进程比较笨重,启动时间更长。在线程方面,Windows建议使用多线程处理。


哦,有趣,那是否意味着对测试平衡的更改,比如更高但更少的计数,会让Windows重新获得一些多处理性能?我会试一下。 - manghole
2
尝试重新校准计数到10,000,000和8次迭代,结果更倾向于Windows:<pre>串行运行花费了1651.000毫秒 并行运行花费了696.000毫秒 线程化运行花费了3665.000毫秒</pre> - manghole

5

有人说在Windows上创建进程比在Linux上昂贵。如果您在网站上搜索,您会找到一些相关信息。这里是我轻松找到的一个


3

启动池需要很长时间。在“现实世界”程序中,我发现如果可以保持一个池保持打开状态并重新使用它用于许多不同的进程,并通过方法调用(通常使用map.async)传递引用,则在Linux上我可以节省几个百分点但是在Windows上我通常可以将花费的时间减半。在我的特定问题上,Linux始终更快,但即使在Windows上,我也从多进程中获得了净利润。


1

目前,你的counter()函数并没有修改太多状态。尝试更改counter()以便它可以修改许多内存页面。然后运行一个CPU绑定循环。看看Linux和Windows之间是否仍存在很大的差异。

我现在没有运行Python 2.6,所以我无法自己尝试。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接