Python多线程与多进程
进程与线程
Python封装了多进程与多线程库,ThreadPool和DummyPool属于多线程,ProcessPool属于多进程。
# 多线程
from multiprocessing.pool import ThreadPool
from multiprocessing.dummy import Pool as DummyPool
# 多进程
from multiprocessing import Pool as ProcessPool
计算密集型任务使用多进程,IO密集型任务使用多线程。
Python有GIL(全局解释器锁),每个CPU在同一时间内只能执行一个线程。
- CPU密集型任务使用多进程:
- Python2.x使用ticks计数达到100即释放GIL,导致CPU密集型任务在for循环等任务中频繁切换线程,消耗资源。
- Python3.x不使用ticks计数而是使用计时,对CPU密集型任务更友好了,但是没有解决GIL导致的每个CPU在同一时间内只能执行一个线程的问题,所以效率依然不高。
- IO密集型任务使用多线程:
- 多线程在遇到IO时自动切换线程,不浪费CPU资源。
并行:同时处理多个任务
并发:以切片式分段串行处理多任务
据说,对于多进程而言,有return会比没有return慢很多很多,对于多线程却只会慢一点点
通用示例
def func(param):
pass
return ...
pool = ThreadPool(4)
res = pool.map(func, iterable)
pool.close() #置状态,不接受新的输入
pool.join() #主线程等待子线程退出
tqdm进度条 与 多线程/多进程的结合 p_tqdm
参考 https://github.com/swansonk14/p_tqdm
pip install p_dqdm
from p_tqdm import p_imap
def add(a, b):
return a + b
iterator = p_imap(add, ['1', '2', '3'], ['a', 'b', 'c'])
for result in iterator:
print(result) # prints '1a', '2b', '3c'
对于输入数据中存在不需要迭代的对象,使用partial
from functools import partial
l1 = ['1', '2', '3']
l2 = ['a', 'b', 'c']
def add(a, b, c=''):
return a + b + c
added = p_map(partial(add, c='!'), l1, l2)
# added == ['1a!', '2b!', '3c!']