假设我想要对一些强化计算进行并行化(而不是I / O限制)。
当然,我不想运行比可用处理器更多的进程,或者我会开始支付上下文切换(以及缓存未命中)。
在心理上,我希望当我在n
中增加multiprocessing.Pool(n)
时,总时间会像这样:
但实际上,我得到了这个:
#!/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看到了这种行为:(如果有人有不同的体验,请告诉我。)
任何解释为什么我开火了多少程序似乎并不重要?或者我的代码有问题吗?
我的猜测:似乎是流程不受处理器限制(即使只有两个进程处于活动状态,它们会继续切换CPU),所以无论如何我都在为上下文切换付费。
参考文献:
编辑:更新了更高常量的图形和代码。
答案 0 :(得分:1)
回答我自己的问题:
首先,我似乎在帖子中犯了错误。使用的CPU疯狂地改变似乎不正确。如果我启动两个CPU密集型进程,它们会不断更改内核,但只能在两个内核之间进行更改我的电脑有4个核心,每个核心有2个,34个软核。核心(用于超线程)。我想现在发生的事情是它们正在改变这些2&#34; soft&#34;核心。 Linux不是这样做的,它是CPU板。
话虽如此,我仍然感到惊讶的是,上下文切换并不比它更痛苦。
编辑:与this blog相比,有一个很好的讨论,比我更好的实证工作。
答案 1 :(得分:0)
事实上,即使n <4,我也看到调度程序在频繁地旋转了 通过我的处理器处理,而不是分配每个进程 它自己的处理器,避免上下文切换。
默认情况下,流程不受处理器限制,其中一个主要原因是避免处理器的不均匀加热,这会导致机械压力并缩短其使用寿命。
有一些方法可以在单个核心上强制运行进程(查看psutil
模块),这样可以更好地利用缓存并避免上下文切换,但在大多数情况下(如果不是全部) ,你的表现并没有太大的不同。
所以现在如果产生的进程多于核心数量,它们只会充当线程并在它们之间切换以优化执行。处理器性能只会(非常)略微降低,因为您已经用少于4个进程切换上下文。