文章插图
多进程处理多进程的改造也非常简单 , 我么只需把之前多线程脚本中的ThreadPoolExecutor替换为ProcessPoolExecutor即可 。
from concurrent.futures import ProcessPoolExecutor...
with ProcessPoolExecutor(max_workers=20) as do: do.map(get_img, pic_ids, urls)执行结果:
图片 9 已经保存!图片 6 已经保存!...图片 11 已经保存!图片 15 已经保存!共耗时4.606秒下载完成也非常快了 , 4秒钟就完成了 , 但是比多线程的3秒 , 稍微慢点 。为什么多进程要比多线程慢呢?顾名思义 , 多进程程序会启用多个进程 , 而多线程会使用线程 。Python中一个进程可以运行多个线程 。每个进程都有其适当的Python解释器和适当的GIL 。相比较而已 , 启动一个进程是更加耗时 , 重的操作 , 所以需要花费的时间更多 。
文章插图
斐波那契数列计算
文章插图
为了进一步说明Python中线程和进程之间的区别 , 我们再来举一个大量计算的例子 , 斐波那契数列的计算 。
根据斐波那契数列的定义我们用递归方法编写实现其计算:
def fib(n): if n == 1: return 0 elif n == 2: return 1 else: return fib(n-1) + fib(n-2)在不使用numpy的情况下用普通Python计算比较慢:
def main(): fib_range = list(range(1, 35)) times = [] for run in range(10): start = time.time() for n in fib_range: fib(n) end = time.time() times.Append(end-start) print('波那契数列fib(35)计算平均耗时 {:.3f} 。'.format(np.mean(times))结果:
波那契数列fib(35)计算平均耗时 5.200下面我们试着用并发计算来加速计算 。
让我们通过线程加速它!为此 , 我用受信任的ThreadPoolExecutor替换for循环 , 如下所示:
with ProcessPoolExecutor() as do: do.map(fib, fib_range)执行结果:
波那契数列fib(35)计算平均耗时 5.239 。什么?加速后 , 反而慢 , 好像多线程没起到作用 。这就是GIL的因素导致的 , 尽管使用了多个线程 , 生成了一堆线程 , 但是这些线程都在同一进程中运行并共享一个GIL 。所以斐波那契序列尽管是并发计算的 , 这些线程在只能在一个CPU上循序执行 。
文章插图
进程可以分布在不同的CPU核心 , 而在同一进程上运行的线程则不能 。使CPU消耗最大的操作为CPU绑定操作 。为了加快CPU限制的操作 , 应该启动多个进程计算 。我们用ProcessPoolExecutor替换ThreadPoolExecutor再试试:
波那契数列fib(35)计算平均耗时 3.591性能提高了一点 。
除了并发的方式外 , 我们可以用算法优化方法来提高性能 , 在数值计算中 , 这是一种更有效的方法 , 比如 , 我们改造fib函数:
def fib(n): a, b, i = 0, 1, 1 while i < n: a, b = b, a + b i += 1 return b上述方法中 , 巧妙用内存存中的变量历史迭代的前两次结果都存在内存中 , 所以该次计算中无需回溯迭代计算 , 这样计算效率O(1) , 基本上可以秒出结果 。
使用新算法后的执行结果:
波那契数列fib(35)计算平均耗时 0.000 。
总结本文我们实例介绍了Python中的并发编程 , 关于并发编程由于标准库中给我们打包好了方便使用的并发函数使得其使用非常方便 。需要注意的是Python中的并发不管是多线程在IO操作中是有效的 , 而在其他方面 , 如数值结算时候就受GIL限制无用了 。关于并发计算和GIL有心的话 , 可以参考有关文档进一步深入学习了解 。
【实例Python并发编程】
推荐阅读
- 如何使用 Python 来自动交易加密货币
- 你的摄像头可能被入侵!教你用Python实现窃取摄像头照片
- 常用的并发工具类
- 如何在你的Android手机上配置 Python 环境?
- Python进阶记录之HTMLParser模块
- 学并发编程,透彻理解这三个核心是关键
- 实战Redis,解决高并发性能问题
- Python爬虫案例,腾讯动漫爬虫,步骤超详细解释,源码分析
- Faust - 简洁高效的 Python 流处理库
- Python虚拟环境实用指南