一、简单理解一下线程和进程
一个进程中可有多个线程,线程之间可共享内存,进程间却是相互独立的。打比方就是,进程是火车,线程是火车厢,车厢内人员可以流动(数据共享)
二、python中的多线程和多进程
当遇到大文件读写或处理计算时,需要加速,则用上多线程和多进程,最常见的例子是网页爬虫,每次访问后等待时间很长,所以用了异步访问。
先说结论,多线程适合IO密集型任务,多进程适合计算密集型任务。
在python中,遇到IO操作,GIL(全局解释锁)会被释放,执行下一个操作,此时用到线程即可,如果开辟进程的话,需要分配初始化的时间和空间。计算密集型用线程则不行,因为若一个计算任务没有完成时,锁不会释放,所以线程相当于串行了。借用知乎上的比喻,有一个水池,4个泵,1个人,人同时只能操作一个泵,则此时相当于串行,但如果泵的工作冷却时间比为1:3,则利用率可以达到100%,其中冷却时间相当于IO操作的等待时间,此时多线程有效。
很多时候python多线程加速有限,除非是IO密集型场景,如爬虫访问网页。
三、python代码
多进程:
from multiprocessing import Pool
pool = Pool(5)
多线程:
from multiprocessing.pool import ThreadPool
pool = TreadPool(5)
四、代码模板
注意pool.apply_async的用法(异步执行)
可视化操作用到pbar
pool.close() #关闭进程池/线程池
pool.join() #阻塞主进程,等待所有子进程结束后再运行
其他话:有时候在jupyterlab中大数据操作时,感觉会有进程间锁死的奇怪问题,或者加速效果不明显的问题,仍需要研究
from multiprocessing import Pool
from multiprocessing.pool import ThreadPool
import math
import datetime
from tqdm import tqdm
from multiprocessing import Pool, cpu_count
import os, time, random
def func(num):
name = num
#for i in tqdm(range(5), ncols=80, desc='执行任务' + str(name) + ' pid:' + str(os.getpid())):
for i in range(5):
# time.sleep(random.random() * 3)
time.sleep(1)
print("finished")
pbar.update()
print("cpu_count():",cpu_count())
pool = Pool(10)
start = time.time()
with tqdm(total=50) as pbar:
for i in (range(50)):
pool.apply_async(func, args=(i,))
pool.close()
pool.join()
end = time.time()
print("\n应用多进程耗时: %0.2f seconds" % (end - start))
print("over")