雷锋网 AI 科技评论按,作为目前最流行的编程语言之一,python 在人工智能相关的领域备受青睐。在编码时,代码的运行时间是我们需要考虑的重要因素之一。如何加快程序运行的速度?这是很多开发者经常会思考的问题。
工程师 Jim Anderson 分享了他的经验,他写了一篇关于「通过并发性加快 python 程序的速度」的文章。Jim 有多年的编程经验,并且使用过各种编程语言。他曾做过嵌入式系统相关的工作,开发过分布式系统,并且参加过许多会议。
如果你听过很多关于 asyncio 被添加到 python 的讨论,但是好奇它与其他并发方法相比怎么样,或者你很好奇什么是并发,以及它如何加速你的程序,那么你需要看下 Jim Anderson 的这篇文章,雷锋网编译整理。
在本文中,你将了解以下内容:
-
什么是并发?
-
什么是并行?
-
一些 python 并发方法的比较,包括线程、异步和多进程
-
在程序中何时使用并发性以及使用哪个模块
本文假设读者对 python 有一个基本的了解,并且使用 python3.6 及以上版来运行示例。你可以从 Real python GitHub repo 下载示例。
什么是并发?
并发这个词在字典里面定义是「同时发生」。在 python 中,同时发生的事情由线程、任务、进程调用,但在高层,它们都是指按顺序运行的一系列指令。
我喜欢把它们看作是不同的思维方式。它们都可以在特定的点上停止,此时,正在处理它们的 CPU 或大脑可以切换到其它的点上。每件事的状态都会被保存,这样它就可以在中断的地方重新启动。
你可能想知道为什么 python 对相同的概念使用不同的词。事实证明,只有从宏观意义上看线程、任务和进程时,它们才是相同的。一旦你开始深入了解细节,它们都代表着一些稍微不同的东西。随着示例的不断深入,你将看到更多不同之处。
你必须小心谨慎,因为当你深入到细节的时候,实际上只有多进程在同一时间运行着多个任务。线程和异步都在单个处理器上运行,因此一次只能处理一个任务。他们只是聪明地找到方法轮流加速整个过程。即使它们不同时运行不同的程序,我们仍然称之为并发。
线程或任务轮流执行的方式是线程和异步之间的巨大区别。在线程中,操作系统实际上知道每个线程,并且可以随时中断它以开始运行不同的线程。这被称为先占式多工法(pre-emptive multitasking),因为操作系统可以对线程进行切换。雷锋网(公众号:雷锋网)
先占式多工法(pre-emptive multitasking)很方便,因为线程中的代码不需要做任何事情来进行切换。但它也是困难的,因为「在任何时候」都可能需要进行任务切换。这种转换可以发生在单个 python 语句的中间,甚至是像 x=x+1 这样的简单语句。
另一方面,asyncio 使用协同多任务处理。这些任务必须通过宣布它们何时准备好被关闭来协同合作。这意味着要实现这一点,任务中的代码必须稍微更改才能实现这一点。
提前做这些额外的工作的好处是,你总是知道你的任务将在哪里被切换。除非该语句被标记,否则任务不会在 python 语句的中间被切换。接下来你将看到如何简化设计的各个部分。
什么是并行?
到目前为止,你已经研究了在单个处理器上发生的并发。那么对于你的新笔记本电脑上的那么多 CPU 核会怎么样呢?你如何利用它们?答案就是多进程。
通过多进程,python 创建了新的进程。这里的一个进程可以被看作是一个完全不同的程序,尽管从技术上讲,它们通常被定义为一个资源的集合,其中的资源包括内存、文件句柄和类似的东西。每个进程都在自己的 python 解释器中运行。
因为它们是不同的进程,所以在多进程中的每一个进程都可以在不同的核上运行。在不同的核心上运行意味着它们实际上可以同时运行,这太棒了。这样做会产生一些复杂的情况,但是在大多数情况下,python 都能很好地平衡它们。
并发何时有用?
并发性可以对两种类型的问题产生很大的影响。这通常称为 CPU 绑定和 I/O 绑定。
I/O 绑定问题会导致程序运行速度减慢,因为它常常需要等待来自某些外部资源的输入/输出(I/O)。当你的程序处理比你的 CPU 慢得多的东西时,这种情况经常发生。
比你的 CPU 慢的事情很多,但谢天谢地,它们中间的大多数都不会与你的程序有关联。你的程序最常与之交互的缓慢的事情是文件系统和网络连接。
让我们看看它们是什么样子的:
在上面的示意图中,蓝色框显示程序工作的时间,红色框显示等待 I/O 操作完成的时间。这个图并不是按比例绘制的,因为 Internet 上的请求时间可能比 CPU 指令长几个数量级,所以你的程序最终可能会花费大部分时间等待操作完成。这是你的浏览器在大多数时间里所做的事情。
另一方面,有一些程序可以在不与网络通信或不访问文件的情况下进行重要的计算。这些是 CPU 绑定的程序,因为限制程序速度的资源是 CPU,而不是网络或文件系统。
以下是 CPU 绑定程序的示意图:
当你完成下面部分中的示例时,你将看到不同形式的并发在 CPU 绑定的程序和 I/O 绑定的程序中工作得更好或更差。向程序添加并发性会增加额外的代码,增大复杂性,因此你需要确定潜在的加速是否值得付出这些代价。看完本文,你应该有足够的信息来开始做这个决定。
关于概念的介绍就到这里啦,下面的文章中,你将看到 I/O 绑定程序相关的内容,之后,你将看到一些处理 CPU 绑定程序的代码。
接下来的部分请查看:
如何利用并发性加速你的python程序(二):I/O 绑定程序加速
如何利用并发性加速你的python程序(三):CPU 绑定程序加速
via:https://www.leiphone.com/news/201901/JfoLltRClm3bZzuB.html?type=preview
雷锋网版权文章,未经授权禁止转载。详情见。
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/134905.html