python multiprocessing问题,为啥输出结果和预期不一样?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python multiprocessing问题,为啥输出结果和预期不一样?相关的知识,希望对你有一定的参考价值。
# encoding=utf-8
import multiprocessing
import os
def proc_func(msg):
print "this is processing - ",msg
print os.getpid()
if __name__ == "__main__":
proc=multiprocessing.Process(
target = proc_func ,
args = ("proc 1",)
)
proc.start()
proc.join()
print "Sub-process done."
运行结果为:
Sub-process done.
问题:为什么不打印this is processing proc1 以及进程id?
然而,Multiprocess本身依然有一些功能上的瓶颈。其中一个重要的是:进程之间不能共享内存(线程间则可以共享内存)。这意味着在进程间交换数据的时候,需要把数据打包、传递,解包。在python的语境下就是:
"pickle from main process to the subprocess;
depickle from subprocess to an object in memory;
pickle and return to the main process;
depickle from main process and return to memory"
(具体详见这个问题下的吐槽)
因此, 在需要在进程间共享巨大的数据包的时候,多进程的表现还不如单进程。
除此之外,当需要运行的程序本身不是计算密集型而是是IO密集型,多进程所增加的读写会抵消掉运算速度的增益;如果程序复杂度根本不需要用并行来解决,那么建立进程(池)的时间很可能比运行程序本身还要慢;另外,在进程池 multiprocessing.Pool(n) 的 n 的选择上,如果选择了多于当前CPU的核心数目的数字( multiprocessing.cpu_count() ),那么在进程之间切换的功夫会大大拉低效率。
建立对线程和进程关系的直观印象,可参考这篇文章。
快速而完整地了解python的全局锁(GIL)问题,参考这篇不错的博客。
为了解 multiprocess 的使用,我做了一些测试,测试环境是4核的Macbook Air。如下:
from multiprocessing import Process, Manager, Pool
1 def f(l):
2 l.reverse()
3
return
4
5 def main():
6
l1 = [random.randrange(0, 100000, 1) for i in range(0, 100000)]
7
l2 = [random.randrange(0, 100000, 1) for i in range(0, 100000)]
8
l3 = [random.randrange(0, 100000, 1) for i in range(0, 100000)]
9
l4 = [random.randrange(0, 100000, 1) for i in range(0, 100000)]
10
l5 = [random.randrange(0, 100000, 1) for i in range(0, 100000)]
11
l6 = [random.randrange(0, 100000, 1) for i in range(0, 100000)]
12
l7 = [random.randrange(0, 100000, 1) for i in range(0, 100000)]
13
s = time.time()
14
for l in [l1, l2, l3, l4, l5, l6, l7]:
15
f(l)
16
print "%s seconds" % (time.time() - s)
17
s = time.time()
18 map(f, [l1, l2, l3, l4, l5, l6, l7])
19
print "%s seconds" % (time.time() - s)
20
p = Pool(4)
21
s = time.time()
22 p.map(f, [l1, l2, l3, l4, l5, l6, l7])
23
print "%s seconds" % (time.time() - s)
24
return
也就是分别测试 f() 对 l1, l2, l3, l4, l5, l6, l7 7个列表的操作时间。先是循环的依次操作,再是python中非常好用的 map() 函数,最后是 multiprocessing 的进程池 multiprocessing.Pool.map() ——进程池中建立了4个 worker process , 也就是说,接下来的任务会被随机地分配给4个进程来完成。
每次操作之前都重新计时,得到了这样的结果:
>>> main()
0.00250101089478 seconds
0.000663995742798 seconds
0.907639980316 seconds
多进程出奇得慢。而 map() 相对于循环操作有很大的效率提升。 参考技术A 你使用的Python版本、平台是什么,以及你是在哪里运行你的程序的?追问
python 2.7,win7平台 ,IDlE(python GUI)运行的程序
追答IDLE只拦截了主进程的输出流,不会拦截子进程的输出流,你需要在cmd中调用python运行你的程序。
以上是关于python multiprocessing问题,为啥输出结果和预期不一样?的主要内容,如果未能解决你的问题,请参考以下文章
python MultiProcessing模块进程间通信的解惑与回顾
python 使用multiprocessing需要注意的问题
python:multiprocessing.Pipe和重定向标准输出
python多进程multiprocessing Pool相关问题