(4)验证apply.async中的get()方法是阻塞的 1.多进程的使用方法
直接给出下面程序代码及注释:
from multiprocessing import Process #从多进程模块中导入Process
import time
def sayHi(name):
print 'Hi my name is %s' % name
time.sleep(3)
for i in range(10):
p = Process(target=sayHi, args=(i,)) #调用多进程使用方法
p.start() #开始执行多进程
程序执行结果如下:
xpleaf@xpleaf-machine:/mnt/hgfs/Python/day6$ python multiprocssing8.py
Hi my name is 2
Hi my name is 3
Hi my name is 6
Hi my name is 1
Hi my name is 4
Hi my name is 5
Hi my name is 0
Hi my name is 7
Hi my name is 8
Hi my name is 9
输出顺序不一致,则是因为屏幕的抢占问题而已,但不同的进程执行是并发的。在执行程序的过程中,可以打开另一个窗口来查看进程的执行情况(上面sleep了3秒,所以速度一定要快):
xpleaf@xpleaf-machine:~$ ps -ef | grep mul*
xpleaf 10468 1827 1 19:34 pts/1 00:00:00 python multiprocssing8.py
print result.get() #get()方法
程序执行结果如下:
xpleaf@xpleaf-machine:/mnt/hgfs/Python/day6$ time python multiprocssing_pool10.py
100
real0m1.066s
user0m0.016s
sys0m0.032s
虽然是定义了进程池的数量为5,但由于这里只执行一个子进程,所以时间为1秒多。
上面的程序可以改写为下面的形式:
from multiprocessing import Process,Pool
import time
def sayHi(num):
time.sleep(1)
return num*num
p = Pool(processes=5)
result = p.map(sayHi,range(3))
for i in result:print i
执行结果如下:
xpleaf@xpleaf-machine:/mnt/hgfs/Python/day6$ python multiprocssing_pool10.py
0
1
4 (2)多个进程多次并发的情况:解释进程池作用以及多进程并发执行消耗切换时间
修改上面的程序代码如下:
from multiprocessing import Process,Pool
import time
def sayHi(num):
time.sleep(1)
return num*num
p = Pool(processes=5)
result_list = []
for i in range(30):
result_list.append(p.apply_async(sayHi, ))
for res in result_list:
print res.get()
程序执行结果如下:
xpleaf@xpleaf-machine:/mnt/hgfs/Python/day6$ python multiprocssing_pool_2_11.py
0
1
4
9
16
25
36
49
64
81
100
121
144
169
196
225
256
289
324
361
400
441
484
529
576
625
676
729
784
841
每一部分数字之间有空白是因为我按了回车键的原因,以让这个结果更加明显,同时也可以知道,上面的30个进程是分6次来完成的,是因为我定义了进程池的数量为5(30/6=5),为了更有说服力,可以看一下程序的执行时间:
xpleaf@xpleaf-machine:/mnt/hgfs/Python/day6$ time python multiprocssing_pool_2_11.py | grep real
real0m6.143s
user0m0.052s
sys0m0.028s
可以看到执行的时间为6秒多,之所以不是6秒是因为主程序本身的执行需要一点时间,同时进程间的切换也是需要时间的(这里为5个进程间的切换,因为每次并发执行的进程数为5个),为了说明这一点,我们可以把pool大小改为100,但依然是并发执行6次,程序代码修改为如下:
from multiprocessing import Process,Pool
import time
def sayHi(num):
time.sleep(1)
return num*num
p = Pool(processes=100)
result_list = []
for i in range(600):
result_list.append(p.apply_async(sayHi, ))
for res in result_list:
print res.get()
再观察一下执行时间:
xpleaf@xpleaf-machine:/mnt/hgfs/Python/day6$ time python multiprocssing_pool_2_11.py | grep real
real0m6.371s
user0m0.080s
sys0m0.128s
虽然相差的时间只是零点几秒,但随着并发执行进程数的增加,进程间切换需要的时间越来越多,程序执行的时间也就越多,特别是当单个进程非常消耗CPU资源时。 (3)验证apply.sync方法是非阻塞的
第一个程序代码的注释中,我们说apply.sync方法是非阻塞的,也就是说,无论子进程是否已经执行完毕,只要主进程执行完毕,程序就会退出,看下面的探索过程,以验证一下。
看下面的程序代码:
from multiprocessing import Process,Pool
import time
def sayHi(num):
time.sleep(10)
return num*num
p = Pool(processes=5)
result_list = []
for i in range(30):
result_list.append(p.apply_async(sayHi, ))
for res in result_list:
print res.get()
先查看程序的执行时间:
xpleaf@xpleaf-machine:/mnt/hgfs/Python/day6$ time python multiprocssing_pool_2_11.py | grep real
for i in range(30):
result_list.append(p.apply_async(sayHi, ))
p.close() #执行p.join()前需要先关闭进程池,否则会出错
p.join() #主进程等待子进程执行完后才结束
查看执行的时间:
xpleaf@xpleaf-machine:/mnt/hgfs/Python/day6$ time python multiprocssing_pool_2_11.py | grep real
real0m18.160s
user0m0.048s
sys0m0.044s
xpleaf@xpleaf-mac
当然,结果就是我们可以预料的了。 (4)验证apply.async中的get()方法是阻塞的
使用apply.sync中的get()方法时,是会阻塞的,即apply.sync会等进程返回执行结果后才会执行下一个进程,其实(2)中的第一个例子就可以体现出来(程序中有get(),于是就忽略apply.async的非阻塞特性,等待子进程返回结果并使用get()获得结果)。这里不妨看下来一个例子,以实现虽然是多进程并发,但是因为get()的缘故,进程是串行执行的。
程序代码如下:
from multiprocessing import Process,Pool
import time
def sayHi(num):
time.sleep(1)
return num*num
p = Pool(processes=5)
for i in range(20):
result = p.apply_async(sayHi, )
print result.get()
程序执行结果如下:
xpleaf@xpleaf-machine:/mnt/hgfs/Python/day6$ time python multiprocssing_pool10.py
0