python多处理:没有递减收益?

时间:2016-01-23 15:10:30

标签: python multithreading multiprocess

假设我想要对一些强化计算进行并行化(而不是I / O限制)。

当然,我不想运行比可用处理器更多的进程,或者我会开始支付上下文切换(以及缓存未命中)。

在心理上,我希望当我在n中增加multiprocessing.Pool(n)时,总时间会像这样:

mockup

  1. 负斜率,因为任务利用并行化
  2. 正斜率因为上下文切换开始使我付出代价
  3. 高原
  4. 但实际上,我得到了这个:

    real

    #!/usr/bin/env python
    
    from math import factorial
    
    
    def pi(n):
        t = 0
        pi = 0
        deno = 0
        k = 0
        for k in range(n):
            t = ((-1)**k)*(factorial(6*k))*(13591409+545140134*k)
            deno = factorial(3*k)*(factorial(k)**3)*(640320**(3*k))
            pi += t/deno
        pi = pi * 12/(640320**(1.5))
        pi = 1/pi
        return pi
    
    import multiprocessing
    import time
    maxx = 20
    tasks = 60
    task_complexity = 500
    x = range(1, maxx+1)
    y = [0]*maxx
    
    for i in x:
        p = multiprocessing.Pool(i)
        tic = time.time()
        p.map(pi, [task_complexity]*tasks)
        toc = time.time()
        y[i-1] = toc-tic
        print '%2d %ds' % (i, y[i-1])
    
    import matplotlib.pyplot as plot
    plot.plot(x, y)
    plot.xlabel('Number of threads')
    plot.xlim(1, maxx)
    plot.xticks(x)
    plot.ylabel('Time in seconds')
    plot.show()
    

    我的机器:i3-3217U CPU @ 1.80GHz×4

    操作系统:Ubuntu 14.04

    在n> 4之后,我看到任务管理器按预期轮换各个进程,因为进程多于处理器。然而,相对于n = 4(我的处理器数量),没有任何惩罚。

    事实上,即使n <4,我也看到调度程序通过我的处理器频繁地旋转进程,而不是将每个进程分配给自己的处理器并避免上下文切换。

    我使用gnome-system-monitor看到了这种行为:(如果有人有不同的体验,请告诉我。)

    gnome-system-monitor

    任何解释为什么我开火了多少程序似乎并不重要?或者我的代码有问题吗?

    我的猜测:似乎是流程不受处理器限制(即使只有两个进程处于活动状态,它们会继续切换CPU),所以无论如何我都在为上下文切换付费。

    参考文献:

    编辑:更新了更高常量的图形和代码。

2 个答案:

答案 0 :(得分:1)

回答我自己的问题:

首先,我似乎在帖子中犯了错误。使用的CPU疯狂地改变似乎不正确。如果我启动两个CPU密集型进程,它们会不断更改内核,但只能在两个内核之间进行更改我的电脑有4个核心,每个核心有2个,34个软核。核心(用于超线程)。我想现在发生的事情是它们正在改变这些2&#34; soft&#34;核心。 Linux不是这样做的,它是CPU板。

话虽如此,我仍然感到惊讶的是,上下文切换并不比它更痛苦。

编辑:this blog相比,有一个很好的讨论,比我更好的实证工作。

答案 1 :(得分:0)

  

事实上,即使n <4,我也看到调度程序在频繁地旋转了   通过我的处理器处理,而不是分配每个进程   它自己的处理器,避免上下文切换。

默认情况下,流程不受处理器限制,其中一个主要原因是避免处理器的不均匀加热,这会导致机械压力并缩短其使用寿命。

有一些方法可以在单个核心上强制运行进程(查看psutil模块),这样可以更好地利用缓存并避免上下文切换,但在大多数情况下(如果不是全部) ,你的表现并没有太大的不同。

所以现在如果产生的进程多于核心数量,它们只会充当线程并在它们之间切换以优化执行。处理器性能只会(非常)略微降低,因为您已经用少于4个进程切换上下文。