cpu密集型任务必须用multiprocessing,因cpython的gil使threading无法加速计算;io密集型则优先选threading或asyncio。

什么时候该用 multiprocessing,而不是 threading
CPU 密集型任务必须用 multiprocessing,因为 threading 在 CPython 下受 GIL 限制,多线程跑计算几乎不提速。
典型场景:图像批量处理、数值模拟、加密解密、大量本地数据聚合(比如用 pandas 做 groupby+apply)。
- IO 密集型(如发 HTTP 请求、读写文件)反而优先选
threading或asyncio,multiprocessing启动开销大,进程间通信成本高 - 如果你的“多进程”代码跑得比单进程还慢,大概率是任务太轻量,或者频繁在进程间传大数据(比如把整个
df传给每个子进程) -
multiprocessing.Pool默认启动和 CPU 核数一样多的进程,但不是越多越好——内存占用会线性增长,Linux 下还可能触发 OOM Killer
Pool.map 和 Pool.apply_async 怎么选
Pool.map 简单直接,适合输入可迭代、函数无副作用、结果顺序必须严格对应输入顺序的场景;apply_async 更灵活,但得自己管理回调和异常。
likeshop单商户开源商城系统,公众号商城、H5商城、小程序商城、安卓APP商城、苹果APP商城代码全开源,免费商用。适用场景:B2C商城,新零售商城,社交电商商城,分销系统商城,分销电商商城,小程序商城,商城源码,商城系统,单商户,多商户,电商系统,直播,uniapp,uni-app,B2B2C,B2B,O2O,ERP,Wechat,交易系统,内容系统,雷达,crm。
-
Pool.map会阻塞直到全部完成,中间一个出错(比如某次计算抛ZeroDivisionError),整个调用就崩,错误堆栈也难定位到具体是第几个输入项 -
apply_async可以配合error_callback捕获子进程异常,也能用get(timeout=...)控制等待时间,避免卡死 - 如果输入数据量极大(比如千万级 ID),别一次性
map全部,改用imap或imap_unordered流式处理,内存更稳
子进程拿不到主进程的变量或类实例
这是最常被卡住的点:子进程是全新 Python 解释器实例,不会自动继承主进程的全局变量、已导入模块状态、数据库连接、日志 handler 等。
立即学习“Python免费学习笔记(深入)”;
- 所有需要的数据,必须显式通过参数传入——注意
list、dict这类可变对象会被序列化(pickle),传过去的是副本,改了不影响主进程 - 不要试图在子进程中调用
logging.info期望它输出到主进程的 logger——得重新配置,或统一用print+ 主进程收集 stdout - 像
torch或tensorflow这种底层库,若主进程已初始化 CUDA 上下文,子进程里再 init 很可能报cudaErrorInitializationError,得在子进程里单独处理设备逻辑
Windows 下启动失败或卡在 “Starting processes…”
Windows 没有 fork,multiprocessing 必须走 spawn 方式重载模块,所以入口代码必须包在 if __name__ == '__main__': 里,否则子进程会递归启动新进程。
- 漏写这个判断,程序可能无限 fork,CPU 占满,任务没跑起来就挂了
- 如果用了
pyinstaller打包,还要额外加--multiprocessing-fork参数,不然打包后运行照样卡住 - 某些 IDE(比如 PyCharm 的默认配置)调试时会干扰
spawn,建议先命令行运行验证逻辑
multiprocessing,而是判断“这活儿到底值不值得拆成多进程”——多数时候瓶颈其实在磁盘 IO 或算法本身,而不是 CPU 核数。









