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

Ric*_*ruz 10 python multithreading multiprocess

假设我想要对一些密集计算(不是I/O绑定)进行并行化.

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

精神上,我希望随着我增加nmultiprocessing.Pool(n),总时间将这样的表现:

小样

  1. 负斜率作为任务利用并行化
  2. 上下文切换的正斜率开始使我付出代价
  3. 高原

但实际上,我得到了这个:

真实

#!/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()
Run Code Online (Sandbox Code Playgroud)

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

操作系统:Ubuntu 14.04

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

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

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

GNOME系统监测

任何解释为什么它似乎并不重要我开了多少个进程?或者我的代码出了什么问题?

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

参考文献:

编辑:更新的图形和代码具有更高的常量.

CoM*_*tel 1

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

默认情况下,进程不受处理器限制,主要原因之一是避免处理器受热不均匀,这可能会导致机械应力并缩短其使用寿命。

有多种方法可以强制在单核上运行进程(查看psutil模块),这具有更好地利用缓存内存和避免上下文切换等优点,但在大多数情况下(如果不是全部),您不会做出大的改变。性能方面的差异。

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