什么是多进程?
我们在多线程 (Threading) 里提到过, 它是有劣势的, GIL 让它没能更有效率的处理一些分摊的任务. 而现在的电脑大部分配备了多核处理器, 多进程 Multiprocessing 能让电脑更有效率的分配任务给每一个处理器, 这种做法解决了多线程的弊端. 也能很好的提升效率.
也就是 电脑有多核的处理器, 多核运算
1.2 创建进程 Process
# 创建进程
"""
添加进程模块 multiprocessing
添加进程的 命令 Process
target=job 表示 要执行的进程 函数名
args=() 表示传入的 参数
name="" 表示进程的名字
"""
import multiprocessing as mp # 多进程模块
import threading as td #多线程模块
def job(a,b):
print("aaaa",a,b)
# 多线程 与多进程的命令对比
if __name__ == "__main__":
# t1= td.Thread(target=job, args=(1,2)) # 添加(创建)线程
p1 = mp.Process(target=job, args=(1, 2)) # 添加(创建)进程
# t1.start()
# t1.join()
p1.start()
p1.join()
1.3 存储进程输出 Queue
# 存储进程输出 Queue
import multiprocessing as mp # 多进程模块
def job(q):
res = 0
for i in range(1000):
res += i + i**2 + i **3
q.put(res)
# 多线程 与多进程的命令对比
if __name__ == "__main__":
q =mp.Queue()
p1 = mp.Process(target=job, args=(q,)) # 加逗号表示 这个可以迭代的东西
p2 = mp.Process(target=job, args=(q,)) # 添加(创建)进程
p1.start()
p2.start()
p1.join()
p2.join()
res1= q.get()
res2= q.get()
print(res1 + res2)
------------------------
499667166000
1.4 效率对比 threading & multiprocessing
# 存储进程输出 Queue
import multiprocessing as mp # 多进程模块
import threading as td
import time
def job(q):
res = 0
for i in range(100000):
res += i + i**2 + i **3
q.put(res)
# 多进程
def multicore():
q =mp.Queue()
p1 = mp.Process(target=job, args=(q,)) # 加逗号表示 这个可以迭代的东西
p2 = mp.Process(target=job, args=(q,)) # 添加(创建)进程
p1.start()
p2.start()
p1.join()
p2.join()
res1= q.get()
res2= q.get()
print("multicore:",res1 + res2)
# 多线程 与多进程结合
def multithreading():
q =mp.Queue()
p1 = td.Thread(target=job, args=(q,)) # 加逗号表示 这个可以迭代的东西
p2 = td.Thread(target=job, args=(q,)) # 添加(创建)进程
p1.start()
p2.start()
p1.join()
p2.join()
res1= q.get()
res2= q.get()
print("multithreading",res1 + res2)
def normal():
res = 0
for _ in range(2):
for i in range(100000):
res += i + i**2 + i **3
print("normal", res)
# 多线程 与多进程的命令对比
if __name__ == "__main__":
st = time.time()
normal()
st1 = time.time()
print("normal time:", st1 - st)
multithreading()
st2 = time.time()
print("multithreading time:", st2 - st1)
multicore()
print("multicore time:", time.time() - st2)
------------------------------
normal 49999666671666600000
normal time: 0.10569334030151367
multithreading 49999666671666600000
multithreading time: 0.13794255256652832
multicore: 49999666671666600000
multicore time: 0.26130223274230957
1.5 进程池 Pool
# 进程池
"""
.Pool() 默认使用系统的全部核
.Pool(processes=2) 指定使用核数
.pool.map() 可使用无限的参数
.pool.apply_async() 只能传入1个参数
"""
import multiprocessing as mp
def job(x):
return x*x
def multicore():
pool= mp.Pool() # 默认启动全部
# pool = mp.Pool(processes=2) # processes 指定启动几个核进程
# map 是可以放入很多个迭代的参数, 自动分配到进程,如果有2个进程,就自动分配
res= pool.map(job,range(10))
print(res)
# apply_async 只能在一个进程里算一个东西,
res = pool.apply_async(job,(2,)) # apply_async 只能传1个参数
print(res.get())
# 如果apply_async 想要达到map 的 效果, 就要把 apply_async 设置成迭代的效应,然后用迭代,把它的值传出来. 列表中的迭代 出来, 一个一个的拿出来
multi_res = [pool.apply_async(job,(i,)) for i in range(10)]
print([res.get() for res in multi_res])
if __name__ == "__main__":
multicore()
----------------------
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
4
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
1.6 共享内存 shared memory
https://docs.python.org/3.5/library/array.html#module-array
import multiprocessing as mp
mp.Value("d", 1)
mp.array("i", [1,2,3]) # 只能定义一维的 数组,不能定义多维的
类型 code | C 类型 | Python 类型 | Minimum size in bytes | Notes |
---|---|---|---|---|
“b” | int | 1 | ||
“B” | int | 1 | ||
“u” | Unicode character | 2 | (1) | |
“h” | int | 2 | ||
“H” | int | 2 | ||
“i” | int | 2 | ||
“I” | int | 2 | ||
“l” | int | 4 | ||
“L” | int | 4 | ||
“q” | int | 8 | (2) | |
“Q” | int | 8 | (2) | |
“f” | float | 4 | ||
“d” | float | 8 |
1.7 进程锁
# 抢共享内存
import multiprocessing as mp
import time
def job(v,num,L):
L.acquire() # 加入了锁 锁住进程
for _ in range(10):
time.sleep(0.1)
v.value += num
print(v.value)
L.release() # 加入了锁 释放进程
def multicore():
l= mp.Lock() # 加入了锁
v = mp.Value("i", 0)
p1 = mp.Process(target=job, args=(v,1,l))
p2 = mp.Process(target=job, args=(v,3,l))
p1.start()
p2.start()
p1.join()
p2.join()
if __name__ == "__main__":
multicore()
--------------------不加进程锁___打印的很乱没有规律
1
5
9
13
17
21
25
29
33
37
4
8
12
16
20
24
28
32
36
40
--------------------加入进程锁___打印的很规律
1
2
3
4
5
6
7
8
9
10
13
16
19
22
25
28
31
34
37
40