Python多处理模块的开销

时间:2018-01-20 00:18:06

标签: python numpy multiprocessing

我在Python中使用multiprocessing模块并期望启动流程,创建队列以及从队列中放入和获取值。但是,如果子流程有足够的工作要做,我预计开销最终会被淘汰。运行一个简单的例子(如下所述),我生成的进程的运行时间大约是从父进程启动的同一进程的10倍,即使对于非常大的作业也是如此。

在下面的代码中,我计算了一系列越来越大的数组的平均值。我比较从父进程调用numpy.mean到从单个生成进程调用相同的mean函数,并在生成的进程中做任何事情(以了解开销成本)。

最初,结果如我所料。从父进程调用mean时,与从生成进程调用%matplotlib import numpy, multiprocessing, pandas def do_nothing(x,q): q.put(x[-1]) def my_mean(x,q): q.put(numpy.mean(x)) def test_mp(f,x): q = multiprocessing.Queue() p = multiprocessing.Process(target=f,args=(x,q)) p.start() p.join() s = q.get() return s ndata = 2**numpy.arange(10,29,2) tr1,tr2,tr3 = [[],[],[]] for n in ndata: x = numpy.random.rand(n) tresults = %timeit -n 1 -r 5 -o -q test_mp(do_nothing,x) tr1.append(tresults) tresults = %timeit -n 1 -r 5 -o -q test_mp(my_mean,x) tr2.append(tresults) tresults = %timeit -n 1 -r 5 -o -q numpy.mean(x) tr3.append(tresults) print("All done") t1,t2,t3 = map(lambda tr : pandas.Series([1000*t.best for t in tr]),[tr1,tr2,tr3]) df = pandas.DataFrame({'n' : ndata, 't1 (do nothing)' : t1, 't2 (my_mean)' : t2, 't3 (mean)' : t3}) display(df) df.plot(x='n',style='.-',markersize=10,logx=True,logy=True) 时相比,总运行时间要快得多。对于小型作业,生成的进程的运行时由开销主导。

然而,令人惊讶的是,对于较大的作业,衍生过程的运行时间始终超过从父进程调用大约10倍的成本。

有人可以为此提供解释吗?这是由于子流程中的内存限制吗?我测试的最大阵列是125MB,500MB和2GB。

以下是代码:

ant

以下是结果。所有计时结果都以毫秒为单位。

enter image description here

enter image description here

1 个答案:

答案 0 :(得分:0)

以下是对正在发生的事情的一些观察:

  • 使用-c中的%timeit标记仅显示父进程的CPU时间,在这种情况下,my_meando_nothing显示基本相同的单位倍。因此父进程在两种情况下都使用相同的CPU时间。

  • 如果没有-c标记,则会计算酸洗过程中的时间,至少在调用my_mean时。为什么do_nothing中没有考虑它仍然是一个谜。 Python解释器是否足够智能以识别do_nothing什么都不做?

  • 还有什么神秘之处:谁在做酸洗?父进程?如果是这样,它不会占用任何CPU时间。所以它必须是衍生过程。

  • 使用线程模块(使用queue.Queue()threading.Thread(),结果更符合预期,即对于足够大的问题,运行时间由所需时间决定计算平均值,对numpy.mean()的调用和生成过程中的同一调用基本上是同一时间。

以下是使用线程模块解决同一问题的时间:

enter image description here

enter image description here