该笔记基于B站视频BV1bK411A7tV
CPU密集型计算与IO密集型计算
CPU密集型计算
CPU密集型计算(也被称为计算密集型)是指系统的硬盘、内存性能相对CPU要好很多,此时,系统运作大部分的状况是CPU Loading 100%,CPU要读/写I/O (硬盘/内存),I/O在很短的时间就可以完成,而CPU还有许多运算要处理,CPU Loading很高。例如,计算1+2+3+…+ 1亿、计算圆周率后几十位、数据分析、压缩解压缩、加密解密、正则表达式搜索等都属于CPU密集型程序。
I/O密集型计算(input/output)
IO密集型计算则是指系统的CPU性能相对硬盘、内存要好很多,此时,系统运作,大部分的状况是CPU在等I/O (硬盘/内存) 的读/写操作,此时CPU Loading并不高。例如,如果需要从多个地方读取数据后汇总,需要读取多张数据库数据表、读取多个redis缓存、请求多个远程服务(RPC或者http)(网络爬虫)、需要读取多个本地文件、,这些都是典型的IO密集型。
python并发编程三种方式
Python中的多进程、多线程和多协程各有其优缺点,适用于不同的场景:
对比
多进程Process(mutiprocessing)
- 优点:
- 可以充分利用多核CPU,提高程序的性能。
- 进程之间相对独立,避免了多个线程之间的资源竞争问题。
- 可以充分利用操作系统的调度算法。
- 缺点:
- 创建和销毁进程的开销较大。
- 进程间通信比较复杂。
- 启动数量少
-适用:CPU密集型计算、运行任务数少
多线程Thread (threading)
- 优点:
- 创建和销毁线程的开销较小。
- 数据共享更方便:线程之间可以直接共享内存,可以方便地进行数据传递和共享。
- 线程间通信较简单。
- 缺点:
- 相比进程:Python中的全局解释器锁(GIL)限制了多线程的并行执行,在CPU密集型任务上并不能充分利用多核处理器。
- 相比协程:启动数量有限制、占用内存资源、线程切换有开销
-适用:IO密集型计算、运行任务数不多
多协程序Coroutine(asyncio)
- 优点:
- 无需线程上下文切换的开销,无需原子操作锁定及同步的开销。
- 方便切换控制流,简化编程模型。
- 高并发+高扩展性+低成本:一个CPU支持上万的协程都不是问题。所以很适合用于高并发处理。
- 缺点:
- 无法利用多核资源:协程的本质是个单线程,它不能同时将单个CPU的多个核用上,协程需要和进程配合才能运行在多CPU上。
- 支持的库有限制(例如不能用requests,需要aiohttp)、代码复杂
-适用:IO密集型计算、运行任务数超多(万级)、有现成库支持的场景
GIL(补充)
全局解释器锁(Global Interpreter Lock,简称 GIL)是一种互斥体(锁),在 CPython 中一次只允许一个线程执行 Python 字节码,CPython 是 Python 的标准实现,也是使用最广泛的实现。之所以需要这个锁,主要是因为 CPython 的内存管理不是线程安全的。
GIL不是Python这个语言的特性。Python是一个编程语言,编程语言是一套抽象的数学规则和限制,Python语言没有要求必须要有GIL。GIL是由Python的解释器引入的工具。除了引入了GIL的CPython解释器外,Python还有很多其他的解释器,例如PyPy,Psyco,JPython,其中JPython就没有GIL,因此Python也可以完全不依赖GIL
graph TD
A[待执行任务]
B{任务特点}
C[使用多进程]
D[使用多线程]
E[使用多协程]
F{需要超多任务量?有现成携程库支持?协程实现复杂度可接受?}
A --> B
B -->|cpu密集型| C
B -->|IO密集型| F
F -->|是| E
F -->|否| D