赞
踩
多线程与多进程的基本概念和优劣以及适用场合可以参见:
https://blog.csdn.net/linraise/article/details/12979473
总结得比较详细,我只在这里做一些测试。
multiprocessing的执行在Windows和Linux下有诸多不同,具体细节和原理可以参考官方说明文件:
https://docs.python.org/2/library/multiprocessing.html
如官方文件所说,在Windows下调用multiprocessing库必须要将Pool或者其它实际运行的代码放到:
if __name__ == '__main__':
之下。否则在子进程中将会复制主进程中的所有内容,并不断循环创建新的子进程,从而造成死循环。
直接上测试代码:
from multiprocessing.dummy import Pool as ThreadPool from multiprocessing import Pool from numpy import * h = 1 def hhh(i): print('t') global h h += 2 return h if __name__ == '__main__': for i in range(4): pool = Pool(2) a = pool.map(hhh,(arange(6))) pool.close() pool.join() print(a) print(h)
运行结果为:
[3, 5, 7, 9, 11, 13]
[3, 5, 3, 7, 9, 5]
[3, 3, 5, 5, 7, 7]
[3, 5, 7, 9, 11, 13]
1
我们可以看到 1)此时使用多进程对全局变量h进行更改,并不会对主进程中h的值造成影响,而会导致子进程中的h值出现资源竞争,导致每次运行结果中h的值可能不同; 2)子程序中的运行结果不会打印到屏幕上
第二点是Python IDLE(Integrated Development and Learning Environment)的问题,具体解释可以参看一个stackflow上的回答:
https://stackoverflow.com/questions/23480498/why-doesnt-print-work-in-python-multiprocessing-pool-map
下面我们尝试使用多线程:
from multiprocessing.dummy import Pool as ThreadPool from multiprocessing import Pool from numpy import * h = 1 def hhh(i): print('t') global h h += 2 return h if __name__ == '__main__': for i in range(4): pool = ThreadPool(2) a = pool.map(hhh,(arange(6))) pool.close() pool.join() print(a)
运行结果为:
t t t t t t [3, 5, 7, 9, 11, 13] tt t t t t [19, 15, 17, 25, 21, 23] tt t t t t [37, 27, 29, 31, 33, 35] t t t tt t [39, 41, 43, 45, 49, 47]
在使用多线程的时候,由于不存在内存复制的问题,所以子进程中对全局变量进行更改也会改变主进程里的值。
在Linux下运行相同的多进程脚本,结果为:
t t t t t t [3, 3, 5, 5, 7, 7] t t t t t t [3, 3, 5, 5, 7, 7] t t t t t t [3, 3, 5, 5, 7, 7] t t t t t t [3, 3, 5, 5, 7, 7]
多线程运行结果类似
其实大部分任务都不需要采用多线程或者多进程处理,因为OS往往会自动把计算任务分配到不同的计算核上。一般而言当程序设计比较多的IO时才需要进行多线程或者多进程处理,另外,我们也可以通过异步IO来处理。
下面的三个例子中,我们分别采用for loop、多进程、多线程的方式来处理相同的计算任务,并观察CPU的使用情况。
from multiprocessing.dummy import Pool as ThreadPool from multiprocessing import Pool from numpy import * import time def test1(i): g = eye(20000) a = dot(g,g) return 1 if __name__ == '__main__': print('start') t0 = time.time() print(t0) for j in arange(4): a = test1(j) t1 = time.time() print(t1-t0)
运行后,我们可以用 top -d 1 查看CPU的使用情况:
%Cpu0 : 69.2 us, 30.8 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu1 : 87.3 us, 12.7 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu2 : 59.2 us, 40.8 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu3 : 63.1 us, 36.9 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu4 : 55.8 us, 44.2 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu5 : 77.5 us, 22.5 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu6 : 58.3 us, 41.7 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu7 : 61.2 us, 38.8 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu8 : 68.9 us, 31.1 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu9 : 31.7 us, 68.3 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu10 : 51.5 us, 47.6 sy, 0.0 ni, 1.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu11 : 62.7 us, 37.3 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu12 : 57.8 us, 42.2 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu13 : 78.4 us, 21.6 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu14 : 86.3 us, 13.7 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu15 : 86.4 us, 13.6 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu16 : 66.0 us, 34.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu17 : 79.6 us, 20.4 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu18 : 62.7 us, 37.3 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu19 : 83.3 us, 16.7 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu20 : 74.8 us, 25.2 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu21 : 78.6 us, 21.4 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu22 : 59.2 us, 40.8 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu23 : 62.1 us, 37.9 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu24 : 58.3 us, 41.7 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu25 : 70.9 us, 29.1 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu26 : 87.4 us, 12.6 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu27 : 67.6 us, 32.4 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu28 : 60.2 us, 39.8 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu29 : 80.6 us, 19.4 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu30 : 58.8 us, 41.2 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu31 : 66.0 us, 34.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
运行结果:
start
1566701203.9319963
219.91857361793518
from multiprocessing.dummy import Pool as ThreadPool from multiprocessing import Pool from numpy import * import time def test1(i): g = eye(20000) a = dot(g,g) return 1 if __name__ == '__main__': print('start') t0 = time.time() print(t0) pool = ThreadPool(2) a = pool.map(test1,arange(4)) t1 = time.time() print(t1-t0)
CPU使用情况:
%Cpu0 : 62.1 us, 37.9 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu1 : 59.8 us, 40.2 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu2 : 76.9 us, 23.1 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu3 : 59.2 us, 40.8 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu4 : 78.6 us, 21.4 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu5 : 56.3 us, 43.7 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu6 : 74.5 us, 25.5 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu7 : 46.6 us, 53.4 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu8 : 76.7 us, 23.3 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu9 : 52.9 us, 47.1 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu10 : 55.9 us, 44.1 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu11 : 52.4 us, 47.6 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu12 : 69.6 us, 30.4 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu13 : 82.5 us, 16.5 sy, 0.0 ni, 1.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu14 : 62.1 us, 37.9 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu15 : 74.8 us, 24.3 sy, 0.0 ni, 1.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu16 : 54.4 us, 45.6 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu17 : 61.2 us, 38.8 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu18 : 68.0 us, 32.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu19 : 56.7 us, 43.3 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu20 : 72.8 us, 27.2 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu21 : 56.3 us, 43.7 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu22 : 69.9 us, 30.1 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu23 : 48.5 us, 51.5 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu24 : 65.0 us, 35.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu25 : 59.2 us, 40.8 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu26 : 58.8 us, 41.2 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu27 : 75.5 us, 24.5 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu28 : 63.5 us, 35.6 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 1.0 si, 0.0 st %Cpu29 : 81.4 us, 18.6 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu30 : 67.6 us, 32.4 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu31 : 94.1 us, 5.9 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
运行结果:
start
1566702050.1495867
221.3780152797699
from multiprocessing.dummy import Pool as ThreadPool from multiprocessing import Pool from numpy import * import time def test1(i): g = eye(20000) a = dot(g,g) return 1 if __name__ == '__main__': print('start') t0 = time.time() print(t0) pool = Pool(2) a = pool.map(test1,arange(4)) t1 = time.time() print(t1-t0)
CPU使用情况:
%Cpu0 : 78.6 us, 21.4 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu1 : 65.0 us, 35.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu2 : 81.6 us, 18.4 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu3 : 75.0 us, 25.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu4 : 85.6 us, 14.4 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu5 : 67.3 us, 32.7 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu6 : 79.6 us, 20.4 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu7 : 69.9 us, 30.1 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu8 : 92.3 us, 7.7 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu9 : 65.0 us, 35.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu10 : 58.3 us, 41.7 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu11 : 61.5 us, 38.5 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu12 : 80.8 us, 19.2 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu13 : 69.2 us, 30.8 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu14 : 58.3 us, 41.7 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu15 : 70.2 us, 29.8 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu16 : 79.6 us, 20.4 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu17 : 60.6 us, 39.4 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu18 : 70.2 us, 29.8 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu19 : 54.9 us, 45.1 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu20 : 35.9 us, 64.1 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu21 : 68.9 us, 31.1 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu22 : 71.8 us, 28.2 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu23 : 61.2 us, 38.8 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu24 : 54.4 us, 45.6 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu25 : 64.4 us, 35.6 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu26 : 57.3 us, 42.7 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu27 : 64.4 us, 35.6 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu28 : 76.0 us, 24.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu29 : 74.0 us, 26.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu30 : 70.9 us, 29.1 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu31 : 64.4 us, 35.6 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
运行结果:
start
1566702305.042819
179.691650390625
我们发现三种方式所需要的计算时间实际上差不多,并且程序在运行时实际上CPU的每一个核都在进行计算,所以一般的计算任务并不需要可以编写多进程或者多线程。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。