- 内容提要
- 前言
- 作者简介
- 封面简介
- 第1章 理解高性能 Python
- 第2章 通过性能分析找到瓶颈
- 2.1 高效地分析性能
- 2.2 Julia 集合的介绍
- 2.3 计算完整的 Julia 集合
- 2.4 计时的简单方法——打印和修饰
- 2.5 用 UNIX 的 time 命令进行简单的计时
- 2.6 使用 cProfile 模块
- 2.7 用 runsnakerun 对 cProfile 的输出进行可视化
- 2.8 用 line_profiler 进行逐行分析
- 2.9 用 memory_profiler 诊断内存的用量
- 2.10 用 heapy 调查堆上的对象
- 2.11 用 dowser 实时画出变量的实例
- 2.12 用 dis 模块检查 CPython 字节码
- 2.13 在优化期间进行单元测试保持代码的正确性
- 2.14 确保性能分析成功的策略
- 2.15 小结
- 第3章 列表和元组
- 第4章 字典和集合
- 第5章 迭代器和生成器
- 第6章 矩阵和矢量计算
- 第7章 编译成 C
- 第8章 并发
- 第9章 multiprocessing 模块
- 第10章 集群和工作队列
- 第11章 使用更少的 RAM
- 第12章 现场教训
第8章 并发
读完本章之后你将能够回答下列问题
什么是并发,它如何起帮助作用?
并发和并行的区别是什么?
什么任务能够用并发来做,什么不能做?
并发的各种模式是什么?
什么时候是利用并发的合适时机?
并发如何来加速我们的程序?
I/O对程序的执行流是相当大的负担。每一次你的代码读取一个文件或者写入一个网络socket,它必须得暂停和内核的联系,请求去启动操作,并等待它完成。这可能看起来并不像是世界末日,尤其当你意识到每次分配内存时只会发生一次简单的操作之后。无论如何,如果我们回溯到图1-3,就会看到我们执行的绝大多数I/O操作在比CPU慢几个数量级的设备上。
例如,一个典型操作大约花费1毫秒来写网络socket,在这期间,我们本应能在一台2.4GHz的电脑上完成24000000条指令。最糟的是,我们的程序暂停超过了1毫秒——我们的执行流暂停下来了,我们正在等待一个写操作完成的信号。在暂停的状态下花费的时间叫作“I/O等待”。
并发允许我们在等待一个I/O操作完成的时候执行其他操作,从而帮助我们把这个浪费的时间利用起来。例如,在图8-1中,我们看到它描述了一个必须运行三个任务的程序,所有任务都在其内具有周期性的I/O等待。如果我们串行地运行它们,我们就会遭受三次I/O等待的惩罚。
无论如何,如果我们并发地运行这些任务,我们基本上就能通过同时运行其他的任务来隐藏掉等待的时间。值得注意的是,这还是都发生在一个单独的线程上,还是每次只使用一个CPU!
尽管并发不局限于I/O,但这是我们所见到的能得到最大收益的地方。在一个并发程序中,与其让你的代码串行执行——那就是,从一行到下一行——不如编写你的代码来处理事件,当不同事件发生时,让你的代码运行于不同的部分。
通过用这种方式对一个程序建模,我们就能够处理我们所关心的特殊事件:I/O等待。
图8-1 串行和并发程序的对比
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论