GIL与多线程
有了GIL的存在,同一时刻同一进程中只有一个线程被执行
多进程可以利用多核,但是开销大,而python的多线程开销小,但却无法利用多核优势
1、cpu到底是用来做计算的,还是用来做I/O的?
2、多个cpu,意味着可以有多个核并行完成计算,所以多核提升的是计算性能,cpu越多计算性能越高
3、无论是多核还是单核CPU ,每个cpu一旦遇到I/O阻塞,仍然需要等待,所以多核对I/O操作没什么用处
CPU用来计算
结论:
1、对计算来说,cpu越多越好,但是对于I/O来说,再多的cpu也没用
2、当然对运行一个程序来说,随着cpu的增多执行效率肯定会有所提高(不管提高幅度多大,总会有所提高),这是因为一个程序基本上不会是纯计算或者纯I/O,
所以我们只能相对的去看一个程序到底是计算密集型还是I/O密集型,从而进一步分析python的多线程到底有无用武之地
假设我们有四个任务需要处理,处理方式肯定是要玩出并发的效果,解决方案可以是:
假设我们有四个任务需要处理,处理方式肯定是要玩出并发的效果,解决方案可以是:
方案一:开启四个进程
方案二:一个进程下,开启四个线程
单核情况下,分析结果:
如果四个任务是计算密集型,没有多核来并行计算,方案一徒增了创建进程的开销,方案二胜
如果四个任务是I/O密集型,方案一创建进程的开销大,且进程的切换速度远不如线程,方案二胜
现在大部分的软件都是IO密集型,所以开多线程
多核情况下,分析结果:
如果四个任务是计算密集型,多核意味着并行计算,在python中一个进程中同一时刻只有一个线程执行用不上多核,方案一胜
如果四个任务是I/O密集型,再多的核也解决不了I/O问题,方案二胜
结论:
现在的计算机基本上都是多核,python对于计算密集型的任务开多线程的效率并不能带来多大性能上的提升,甚至不如串行(没有大量切换),但是,对于IO密集型的任务效率还是有显著提升的。
多线程性能测试
如果并发的多个任务是计算密集型:多进程效率高
多进程耗时17秒
from multiprocessing import Process import os import time def work(): res = 0 for i in range(100000000): res *= i if __name__ == '__main__': l = [] print(os.cpu_count()) # 查看主机是CPU多少核 start=time.time() for i in range(4): p = Process(target=work) # 多进程耗时17秒 l.append(p) p.start() for p in l: p.join() stop=time.time() print('run time is %s' %(stop-start)) ''' 4核 run time is 17.621007680892944 '''
多线程耗时28秒
from threading import Thread import os import time def work(): res = 0 for i in range(100000000): res *= i if __name__ == '__main__': l = [] print(os.cpu_count()) # 查看主机是CPU多少核 start=time.time() for i in range(4): p = Thread(target=work) # 多线程耗时28秒 l.append(p) p.start() for p in l: p.join() stop=time.time() print('run time is %s' %(stop-start)) ''' 4核 run time is 28.117608308792114 '''
如果并发的多个任务是I/O密集型:多线程效率高
模拟IO密集型 time.sleep等待
多线程耗时2秒
线程来回切换,遇到IO切换到另外一个线程
# IO密集型:用多线程 from threading import Thread import os import time def work(): time.sleep(2) if __name__ == '__main__': l = [] print(os.cpu_count()) start=time.time() for i in range(400): p = Thread(target=work) #多线程耗时2s多 l.append(p) p.start() for p in l: p.join() stop = time.time() print('run time is %s' %(stop-start)) ''' 4核 run time is 2.0911200046539307 '''
多进程耗时42秒多
from multiprocessing import Process import os import time def work(): time.sleep(2) if __name__ == '__main__': l = [] print(os.cpu_count()) start = time.time() for i in range(400): p = Process(target=work) #多进程耗时2s多 l.append(p) p.start() for p in l: p.join() stop = time.time() print('run time is %s' %(stop-start)) ''' 4 run time is 42.8494508266449 '''
应用:
多线程用于IO密集型,如socket,爬虫,web
多进程用于计算密集型,如金融分析