为什么相同的作业使用python的多处理以不同的速度运行.Pool?

时间:2015-11-09 19:57:42

标签: python multiprocessing

我试图通过在运行Suse Linux的24核的机器上使用python的多处理模块来加速一些繁重的模拟。通过阅读文档,我理解这只有在个人计算所需的时间比创建池等的开销要长得多时才有意义。

让我感到困惑的是,多处理过程中某些单个进程的执行时间远远超过我运行单个进程的时间。在我的实际模拟中,时间从大约300s增加到1500s。有趣的是,当我使用更多进程时,这会变得更糟。

以下示例说明了稍微更短的虚拟循环的问题:

from time import clock,time
import multiprocessing
import os


def simulate(params):
    t1 = clock()
    result = 0
    for i in range(10000):
        for j in range(10000):
            result+=i*j
    pid = os.getpid()
    print 'pid: ',pid,' sim time: ',clock() - t1, 'seconds'
    return result

if __name__ == '__main__':


    for n_procs in [1,5,10,20]:
        print n_procs,' processes:'
        t1 = time()
        result = multiprocessing.Pool(processes = n_procs).map(simulate,range(20))
        print 'total: ',time()-t1

这会产生以下输出:

1  processes:
pid:  1872  sim time:  8.1 seconds
pid:  1872  sim time:  7.92 seconds
pid:  1872  sim time:  7.93 seconds
pid:  1872  sim time:  7.89 seconds
pid:  1872  sim time:  7.87 seconds
pid:  1872  sim time:  7.74 seconds
pid:  1872  sim time:  7.83 seconds
pid:  1872  sim time:  7.84 seconds
pid:  1872  sim time:  7.88 seconds
pid:  1872  sim time:  7.82 seconds
pid:  1872  sim time:  8.83 seconds
pid:  1872  sim time:  7.91 seconds
pid:  1872  sim time:  7.97 seconds
pid:  1872  sim time:  7.84 seconds
pid:  1872  sim time:  7.87 seconds
pid:  1872  sim time:  7.91 seconds
pid:  1872  sim time:  7.86 seconds
pid:  1872  sim time:  7.9 seconds
pid:  1872  sim time:  7.96 seconds
pid:  1872  sim time:  7.97 seconds
total:  159.337743998
5  processes:
pid:  1906  sim time:  8.66 seconds
pid:  1907  sim time:  8.74 seconds
pid:  1908  sim time:  8.75 seconds
pid:  1905  sim time:  8.79 seconds
pid:  1909  sim time:  9.52 seconds
pid:  1906  sim time:  7.72 seconds
pid:  1908  sim time:  7.74 seconds
pid:  1907  sim time:  8.26 seconds
pid:  1905  sim time:  8.45 seconds
pid:  1909  sim time:  9.25 seconds
pid:  1908  sim time:  7.48 seconds
pid:  1906  sim time:  8.4 seconds
pid:  1907  sim time:  8.23 seconds
pid:  1905  sim time:  8.33 seconds
pid:  1909  sim time:  8.15 seconds
pid:  1908  sim time:  7.47 seconds
pid:  1906  sim time:  8.19 seconds
pid:  1907  sim time:  8.21 seconds
pid:  1905  sim time:  8.27 seconds
pid:  1909  sim time:  8.1 seconds
total:  35.1368539333
10  processes:
pid:  1918  sim time:  8.79 seconds
pid:  1920  sim time:  8.81 seconds
pid:  1915  sim time:  14.78 seconds
pid:  1916  sim time:  14.78 seconds
pid:  1914  sim time:  14.81 seconds
pid:  1922  sim time:  14.81 seconds
pid:  1913  sim time:  14.98 seconds
pid:  1921  sim time:  14.97 seconds
pid:  1917  sim time:  15.13 seconds
pid:  1919  sim time:  15.13 seconds
pid:  1920  sim time:  8.26 seconds
pid:  1918  sim time:  8.34 seconds
pid:  1915  sim time:  9.03 seconds
pid:  1921  sim time:  9.03 seconds
pid:  1916  sim time:  9.39 seconds
pid:  1913  sim time:  9.27 seconds
pid:  1914  sim time:  12.12 seconds
pid:  1922  sim time:  12.17 seconds
pid:  1917  sim time:  12.15 seconds
pid:  1919  sim time:  12.17 seconds
total:  27.4067809582
20  processes:
pid:  1941  sim time:  8.63 seconds
pid:  1939  sim time:  10.32 seconds
pid:  1931  sim time:  12.35 seconds
pid:  1936  sim time:  12.23 seconds
pid:  1937  sim time:  12.82 seconds
pid:  1942  sim time:  12.73 seconds
pid:  1932  sim time:  13.01 seconds
pid:  1946  sim time:  13.0 seconds
pid:  1945  sim time:  13.74 seconds
pid:  1944  sim time:  14.03 seconds
pid:  1929  sim time:  14.44 seconds
pid:  1943  sim time:  14.75 seconds
pid:  1935  sim time:  14.8 seconds
pid:  1930  sim time:  14.79 seconds
pid:  1927  sim time:  14.85 seconds
pid:  1934  sim time:  14.8 seconds
pid:  1928  sim time:  14.83 seconds
pid:  1940  sim time:  14.88 seconds
pid:  1933  sim time:  15.05 seconds
pid:  1938  sim time:  15.06 seconds
total:  15.1311581135

我不明白的是,某些进程在一定数量的CPU之上变得慢得多。我应该补充一点,这台机器上没有其他东西在运行。这是预期的吗?难道我做错了什么?

3 个答案:

答案 0 :(得分:2)

核心是计算机上的其他任何共享资源。

操作系统通常会平衡负载。这意味着它将在尽可能多的核心上传播线程。*指导度量将是核心负载。

因此,如果线程数较少,那么核心数会使某些核心处于空闲状态。 (线程架构防止分裂到多个核心上。)

如果有更多线程,那么核心。操作系统会将许多线程分配给单核,并在该核心上的那些线程之间进行多任务处理。在单核上从一个线程切换到另一个线程会产生一些成本。

将任务从核心转移到另一个核心的成本更高。 (在两个核心资源方面相当重要)操作系统通常会避免此类操作。

回到你的故事。

性能让线程数达到核心数,因为那里有空闲核心可以获得新的工作。尽管那些忙于操作系统工作的最后核心很少,所以那些对实际性能的贡献很少。

线程计数超过核心数后,

整体性能仍有提升。只是因为如果以前卡在长时间运行的任务(如I / O)上,OS可以切换活动线程,那么另一个可以使用CPU时间。

如果线程计数会显着超过核心数,

Perofrmance会降低。由于太多的线程会争夺相同的资源(CPU时间),并且转换成本会聚合到大部分CPU周期。但是,从您的列表中,它仍未发生。

至于看似很长的执行时间?很长!只是线程并没有把它全部用完。操作系统关闭和打开它们,以便在任何人遇到外部工作(I / O)时最大限度地提高CPU使用率,然后在分配给核心的线程中更多地切换到更均匀地分散CPU时间。

*操作系统也可能用于最少的电源使用,最大化I / O使用等。特别是Linux在这里非常灵活。但它超出范围;)如果感兴趣,请阅读Linux中的各种调度程序。

答案 1 :(得分:0)

这是在查看不同的问题和文档后我能想出的最佳答案:

众所周知,multiprocessing在运行时性能方面通常会增加某种开销。这可能是很多不同因素的结果,例如分配RAM空间,初始化进程,等待终止,etc,etc,etc。这就解释了从单一切换到并行处理的时间增加。

随着进程数量的增加,时间的增加可以通过多重处理的工作方式来解释。 ali_m in this link的评论是我能找到的最好的解释为什么会发生这种情况:

  

对于初学者来说,如果您的线程共享CPU缓存,您可能会遭受更多缓存未命中,这可能会导致性能大幅下降

当您尝试在计算机上同时运行许多不同的程序时,这是相似的:您的程序开始“延迟”。并且因为你的CPU一次只能处理这么多请求而减速。

我找到的另一个好的链接是this。虽然这是关于SQL服务器和使用查询的问题,但可以应用相同的想法(关于随着进程/查询量的增加而产生的开销量)

到目前为止,这不是一个完整的答案,但这是我对你为何得到结果的轻微理解。结论?您获得的结果或正常和预期的多处理结果

答案 2 :(得分:0)

这个问题的答案使问题变得多余。 事实证明,该机器只有12个物理内核,每个内核可以接受两个线程。

multiprocessing.cpu_count()的输出为24.但lscpu表示只有两个插槽,每个插槽有六个内核。

这解释了为什么在十个以上的过程中,个别运行变慢。