在Python中,并行计算是指同时利用多个计算资源(如多核CPU、多机集群)执行多个独立任务,以提升程序运行效率。以下是核心概念的分步解析:
1. 并行 vs 并发
- 并行:真正的多任务同时进行(如多核CPU同时处理不同任务)。
- 并发:通过快速切换任务实现“看似同时”执行(如单线程中的异步I/O)。
Python中由于全局解释器锁(GIL)的存在,多线程更适合I/O密集型任务,而多进程更适合CPU密集型任务。
2. 并行计算的常见实现方式
① 多进程(Multiprocessing)
- 利用
multiprocessing
模块创建子进程,绕过GIL限制。 - 适用场景:CPU密集型任务(如数值计算、图像处理)。
- 示例:
from multiprocessing import Pool def square(x): return x * x if __name__ == "__main__": with Pool(4) as p: # 创建4个进程 results = p.map(square, [1, 2, 3, 4, 5]) print(results) # 输出: [1, 4, 9, 16, 25]
② 多线程(Threading)
- 使用
threading
模块创建线程,适合I/O密集型任务(如文件读写、网络请求)。 - 注意:受GIL限制,多线程无法真正并行执行CPU密集型任务。
③ 异步编程(Asyncio)
- 基于事件循环和协程,适合高并发I/O密集型场景(如Web服务器)。
- 示例:
import asyncio async def fetch_data(url): # 模拟异步I/O操作 await asyncio.sleep(1) return f"Data from {url}" async def main(): tasks = [fetch_data("url1"), fetch_data("url2"), fetch_data("url3")] results = await asyncio.gather(*tasks) print(results) asyncio.run(main())
④ 高级库简化并行
concurrent.futures
:统一接口管理进程池/线程池。from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor def task(x): return x * x # 使用线程池 with ThreadPoolExecutor() as executor: results = list(executor.map(task, [1, 2, 3])) # 使用进程池 with ProcessPoolExecutor() as executor: results = list(executor.map(task, [1, 2, 3]))
Dask
/Joblib
:分布式计算库,适合大规模数据并行。
3. 并行计算的优缺点
优势 | 挑战 |
---|---|
显著提升计算密集型任务速度 | 代码复杂度增加 |
利用多核/多机资源 | 进程间通信(IPC)成本较高 |
适合处理大规模数据 | 调试和错误处理更复杂 |
4. 适用场景
- CPU密集型任务:数值计算、机器学习模型训练(用多进程)。
- I/O密集型任务:文件下载、API请求(用多线程/异步)。
- 大规模数据处理:使用Dask或Spark分布式框架。
5. 注意事项
- 避免过度并行:进程/线程数不宜超过CPU核心数。
- 减少进程间通信:尽量让任务独立,避免共享状态。
- 使用队列(Queue):进程间传递数据时使用安全队列。
- 监控资源:防止内存泄漏或CPU过载。
通过合理选择并行策略,Python可以高效处理复杂计算任务。对于简单需求,优先使用concurrent.futures
;对于分布式场景,可探索Dask或Ray等库。