我希望使用u ** 2
模块加快u
multiprocessing
的计算速度,其中multi.py
是一个numpy数组。
这是我的尝试(文件名# to compile on Windows/Ipython : import multi then run -m multi
from multiprocessing import Pool
import numpy as np
if __name__ == '__main__':
u=np.arange(6e7)
def test(N):
pool = Pool(N)
v=len(u)//N
tasks = [ u[k*v:(k+1)*v] for k in range(N)]
res = pool.map_async(np.square,tasks).get()
return res
):
In [25]: %time r1=test(1)
Wall time: 13.2 s
In [26]: %time r2=test(2)
Wall time: 7.75 s
In [27]: %time r4=test(4)
Wall time: 8.29 s
In [31]: %time r=u**2
Wall time: 512 ms
以下是基准:
u ** 2
我的PC上有2个物理内核,因此测试(2)比测试(1)运行得更快是令人鼓舞的。
但目前,numpy更快。多处理增加了大的过载。
所以我的问题是:multiprocessing
如何(或可能)加快//This span is used to measure the size of the textarea
//it should have the same font and text with the textarea and should be hidden
var span = $('<span>').css('display','inline-block')
.css('word-break','break-all')
.appendTo('body').css('visibility','hidden');
function initSpan(textarea){
span.text(textarea.text())
.width(textarea.width())
.css('font',textarea.css('font'));
}
$('textarea').on({
input: function(){
var text = $(this).val();
span.text(text);
$(this).height(text ? span.height() : '1.1em');
},
focus: function(){
initSpan($(this));
},
});
的速度?
修改
我意识到所有过程工作都是在他自己的内存空间中完成的,因此必然会产生大量的副本(See here for example)。因此没有希望通过这种方式加快简单计算。
答案 0 :(得分:2)
由于Global Interpreter Lock,CPython中的多处理本身成本很高,这可以防止多个本机线程同时执行相同的Python字节码。 multiprocessing
通过为每个工作进程生成一个单独的Python解释器,并使用pickling来发送参数并从工作者返回变量来解决这个限制。不幸的是,这需要很多不可避免的开销。
如果你绝对必须使用multiprocessing
,建议尽可能多地对每个进程进行一次工作,以尽量减少产生和杀死的相对时间流程。例如,如果您正在并行处理较大阵列的块,则使块尽可能大,并且可以一次执行尽可能多的处理步骤,而不是多次循环遍历阵列。 / p>
但是,一般情况下,使用不受GIL限制的低级语言进行多线程处理会更好。对于简单的数值表达式,例如你的例子,numexpr
是一种非常简单的方法来实现显着的性能提升(~4倍,在具有4核和超线程的i7 CPU上)。除了在C ++中实现并行处理之外,更重要的好处是它避免为中间结果分配内存,从而更有效地使用缓存。
In [1]: import numexpr as ne
In [2]: u = np.arange(6e7)
In [3]: %%timeit u = np.arange(6e7)
.....: u**2
.....:
1 loop, best of 3: 528 ms per loop
In [4]: %%timeit u = np.arange(6e7)
ne.evaluate("u**2")
.....:
10 loops, best of 3: 127 ms per loop
最后,我还要提到除了CPython之外还有其他Python实现缺少GIL,例如PyPy,Jython和IronPython。然而,这些都受到其自身的限制。据我所知,他们都没有为numpy,scipy或matplotlib提供适当的支持。
答案 1 :(得分:0)
我自己回答:
来自scipy-cookbook,恕我直言被低估的功能:
当numpy正在进行数组操作时,python也会释放GIL。
因此多线程不是numpy操作的问题。
from threading import Thread
import numpy as np
u=np.arange(6*10**7)
def multi(N):
n=u.size//N
threads = [Thread(target=np.ndarray.__ipow__,
args=(u[k*n:(k+1)*n],2)) for k in range(N)]
for t in threads: t.start()
for t in threads: t.join()
在2核处理器上获得近2倍的增益:
In [7]: %timeit test(1)
10 loops, best of 3: 172 ms per loop
In [8]: %timeit test(4)
10 loops, best of 3: 92.7 ms per loop