Python并行编程1并行编程简介(上)高频面试题:GIL历程线程协程
1 并行编程简介首先,我们将讨论允许在新盘算机上并行实行的硬件组件,如 CPU 和内核,然后讨论操纵系统中真正推动并行的实体:历程和线程。随后,将具体说明并行编程模型,介绍并发性、同步性和异步性等基本概念。
介绍完这些一般概念后,我们将讨论全局解释器锁(GIL)及其带来的问题,从而相识 Python 在这方面的特殊性,尤其是在线程方面。我们将提到尺度的 Python 库模块,如线程和多处置惩罚,我们将在接下来的章节中更深入地介绍这些模块。最后,我们将通过讨论并行程序的评估方法(如加速和缩放)来竣事本章,并讨论并行编程可能带来的问题(比赛条件、死锁等)。
在本章竣事时,你将明白并行编程背后的全部基本概念和术语。您将在脑海中构建一个总体方案,其中将包含并行实行的全部主角,以及他们是如何实现并行实行的。然后,您就可以着手处置惩罚后续章节中涉及的编程实践部分了。
内容:
[*]CPU 和内核
[*]历程和线程
[*]并行和并发编程
[*]使用 Python 的 GIL 和线程
[*]加速和扩展
1.1 并行编程
新硬件技能的出现让我们有机会在电脑上同时运行多个程序。究竟上,我们的电脑,即使是最简单的电脑,都有一个多核系统,允许程序并行运行。那为什么不使用这种架构呢?
你常常会发现自己正在开发一个 Python 程序来实行一系列操纵。在科学领域,常常必要实现一系列算法来进行非常费力的盘算。但在工作竣事后,在盘算机上运行程序时,你会失望地发现,它并没有你盼望的那么快,而且随着处置惩罚问题的规模增大,实行时间也变得过长。但这不仅仅是速率问题。现在,我们必要处置惩罚的数据量越来越大,与之相干的盘算也越来越多,程序必要的内存资源也越来越大,而我们的盘算机尽管功能强大,却无法处置惩罚这些数据。
并行编程可以同时实行一个程序的部分代码,从而大大提高性能。因此,并行编程意味着收缩程序的实行时间,更有效地使用资源,并能实行从前无法完成的更复杂的操纵。
1.2 盘算机和并行技能的发展
并行概念是随着盘算机内部硬件的发展而逐步形成的。在 20 世纪 80 年代之前,盘算机的功能非常有限:它们以严格的顺序方式,一条指令接一条指令地运行一个程序。显然,在如许的技能环境中,并行的概念甚至连想都不敢想。
https://img2024.cnblogs.com/blog/3174021/202411/3174021-20241114192426229-1156309982.png
随着英特尔 80386 处置惩罚器的问世,盘算机有了中断一个程序的实行以实行另一个程序的可能性。因此,抢占式编程和时间分割等概念应运而生。这一技能进步带来了伪并行结果,因为用户可以看到多个程序同时运行。在随后的英特尔 80486 处置惩罚器中,通过引入基于将程序细分为子使命的流水线系统,情况得到了进一步改善。这些子使命在不同程序之间交替独立实行。别的,内部架构首次实现了将多个不同指令(甚至来自不同程序的指令)组合在一起,并同时(但不是同时)实行。这就是并发编程的真正发展。不同子使命的指令部分都已完成,以便尽快实行:
https://img2024.cnblogs.com/blog/3174021/202411/3174021-20241114193159051-838715868.png
这种情况持续了十多年,功能越来越强大的处置惩罚器型号相继问世,工作频率比从前更高。但由于一系列问题和物理限定,这种情况很快就陷入了危机。提高实行频率意味着同时增加发热量和随之而来的能耗。显然,频率的提升很快就会达到极限。
就如许,处置惩罚器实现了创新的飞跃,在系统中引入了内核。这些内核也被称为逻辑处置惩罚器,可以在单个 CPU 中模拟多个处置惩罚器的存在,从而形成多核 CPU。实际上,多处置惩罚器盘算机可以同时并行实行不同程序的指令。因此,在本世纪初,并行编程技能应运而生,为开发人员同时实行同一程序的不同部分提供了可能。
1.3 CPU、内核、线程和历程
Windows 中的使命管理器可以及时监控各种资源的消耗情况,如 CPU、内存和 Wi-Fi 网络:
https://img2024.cnblogs.com/blog/3174021/202411/3174021-20241114200944149-997822344.png
别的,使命管理器还显示了各种信息,如历程数和当前运行的线程数。右侧则列出了我们正在运行的系统的一些特征,如内核数。
假如你使用的是 Ubuntu 等 Linux 系统,则可使用top:
https://img2024.cnblogs.com/blog/3174021/202411/3174021-20241114201022102-848699575.png
Linux 系统更机动、更强大,特别是由于有大量的 shell 命令,我们还可以监控与每个命令相干的全部线程。为此,我们将使用更具体的命令来监控历程:https://img2024.cnblogs.com/blog/3174021/202411/3174021-20241114201122679-1294733589.png
-T选项用于表示将显示与历程相干的线程。
中央处置惩罚器(CPU Central Processing Unit)是盘算机的真正大脑,基本上是处置惩罚代码的地方。中央处置惩罚器以周期为特征,即中央处置惩罚器在处置惩罚器上实行操纵所使用的时间单位。通常,我们用每秒周期频率来表示 CPU 的功率。
CPU 内部可以有一个内核(单核 CPU)或多个内核(多核 CPU)。内核是 CPU 中的数据实行单元。每个内核可运行多个历程。历程本质上是在机器上运行的程序,并为其预留部分内存。别的,每个历程还可以反过来启动其他历程(子历程),或在其中运行一个(主线程)或多个线程。
https://img2024.cnblogs.com/blog/3174021/202411/3174021-20241114201502998-1271587584.png
反过来,线程也可视为在单个处置惩罚器中并发运行的子历程。与历程一样,线程也有一系列类似的机制来管理它们的同步、数据互换和实行过程中的状态转换(就绪、运行和阻塞)。
这就是我们必须牢记的总体框架,以便更好地明白机器中的历程和线程是如何运行的,从而以最佳方式建立并行编程模型。
1.4 并发和并行编程
并发和并行常常被混淆,这两个术语被互换使用的情况并不少见,但这是不精确的。这两个概念虽然密切相干,但在并行编程中却有所不同,相识其中的区别非常重要。
我们先来看看这两个概念的共同点。当我们的程序必须同时实行多个使命时,就会出现并发和并行。但这正是并发的寄义。
并发意味着同时管理(而非实行)多个使命,但它们并不肯定同时运行。
https://img2024.cnblogs.com/blog/3174021/202411/3174021-20241114201653785-1044607159.png
https://img2024.cnblogs.com/blog/3174021/202411/3174021-20241114201700815-403468480.png
参考资料
[*]软件测试精品册本文档下载持续更新 https://github.com/china-testing/python-testing-examples 请点赞,谢谢!
[*]本文涉及的python测试开发库 谢谢点赞! https://github.com/china-testing/python_cn_resouce
[*]python精品册本下载 https://github.com/china-testing/python_cn_resouce/blob/main/python_good_books.md
[*]Linux精品册本下载 https://www.cnblogs.com/testing-/p/17438558.html
1.5 Python 中用于并发和并行模型的线程和历程
在相识了并发编程和并行编程的区别之后,让我们再进一步。在许多编程语言中,通常的做法是将线程与并发、历程与并行联系起来。究竟上,操纵系统的这两个实体包含了并发和并行这两种不同的功能。
然而,就 Python 而言,将这些情况分为两种不同的编程模型是不错的选择。究竟上,Python 中的线程并不像操纵系统中的线程那样表现完善。Python 中的线程不能并发运行,因此不能并行操纵。在 Python 中使用线程就像是在使用单核 CPU,尽管究竟并非如此。
1.5.1 Python 线程问题:GIL
与其他编程语言不同,Python 中的线程不能在两个不同的内核上同时实行,这与 Python 解释器本身密切相干。究竟上,Python 代码不停运行的解释器是在 CPython 中实现的,在实现过程中,人们发现它并不是完全线程安全的。也就是说,越多的线程试图共同访问某个对象(线程之间共享内存),往往就会由于比赛条件现象而陷入不同等的状态。为了避免这个大问题,解释器中加入了全局解释器锁 (GIL)。因此,Python 筹划者选择在一个历程中,一次只能实行一个线程,从而消除了这种实体的并行性(无多线程)。
但情况并没有那么糟糕。究竟上,稍后我们将看到如何在并行编程模型中调整 Python 语言线程的这一特性。别的,许多外部库并不依靠于 GIL,因为它们是用其他语言(如 C 和 Fortran)实现的,因此可以使用使用多线程的内部机制。NumPy 正是这些库中的一个,它是 Python 数值盘算的基础库。
1.5.2 取消 GIL 以实现多线程盘算
Python 3.13引入了一个名为"free-threaded"的实行性功能,允许在肯定条件下选择性地关闭GIL。这为未来完全解除GIL奠定了基础。 即使启用了"free-threaded"功能,也并非全部场景下都能完全发挥多核CPU的性能。一些复杂的情况可能仍受到GIL的影响。
对于CPU密集型使命,使用多历程可以绕过GIL的限定,充分使用多核CPU。
将Python代码中的性能瓶颈部分用Cython编写,可以得到接近C语言的实行效率,同时又能享受Python的便利性。
如Jython、PyPy等,它们对GIL的处置惩罚方式不同,可能更适合某些特定的应用场景。
1.5.3 Python 中的线程与历程
特点历程线程独立性独立性高,一个历程崩溃不会影响其他历程独立性较低,一个线程崩溃可能导致整个历程崩溃资源开销创建和烧毁历程开销较大,资源消耗相对较高创建和烧毁线程开销较小,资源消耗较低通信历程间通信相对复杂,通常必要使用IPC机制线程间通信相对简单,可以直接共享历程内存空间切换开销历程切换开销较大线程切换开销较小适用场景CPU密集型使命,独立的子使命,必要隔离的程序I/O密集型使命,必要共享数据的并发使命1.5.4 Python 中的并发与并行
在 Python 中使用线程进行并发编程,这些线程各自独立实行使命,并相互竞争实行。
https://img2024.cnblogs.com/blog/3174021/202411/3174021-20241114203332781-1273725107.png
历程非常适合同时实行使命,即并行实行。
https://img2024.cnblogs.com/blog/3174021/202411/3174021-20241114203400266-760093091.png
1.5.5 greenlet的轻并发(Coroutine 协程)
除了线程,Python 还提供了另一种可能的选择:greenlet。从竞争的角度来看,使用greenlet和线程是等价的,因为在 Python 中,线程从来都不是并行实行的,因此使用这种编程语言,两者都能完善地进行并发编程。但创建和管理小绿点所需的资源要比线程少得多。这就是为什么在编程中使用它们被定义为轻并发的原因。因此,当你必要管理大量简单的 I/O 功能(如网络服务器中的功能)时,通常会使用greenlet。我们将在本书后面通过几个简单的例子来相识如何创建和管理 greenlet。
特点线程协程上下文切换操纵系统内核调度,开销较大用户态调度,开销较小创建开销较高较低并发模型多线程协作式多使命应用场景CPU密集型使命、并行盘算I/O密集型使命、异步编程1.5.6 使用 Python 进行并行编程
相识线程和历程在 Python 中的作用。我们可以深入研究与 Python 语言密切相干的并行编程。
因此,在这种语言中,并行编程完满是在历程上表现出来的。一个程序被划分为多个可并行的子使命,每个子使命分配给不同的历程。在每个子使命中,我们可以选择是同步实行还是异步实行各个步调。
1.5.7 同步和异步编程
在本书和许多有关并行编程的在线文档中,常常会提到同步或异步这两个术语,有时也称为sync和async。在全部这些情况下,我们指的是两种不同的编程模型。
在不知不觉中,当我们在多个历程或线程之间并行或竞争地实行一个程序时,我们会自然而然地将其结构化为同步。这是因为一般来说,我们都是串行编程出身,倾向于如许思考问题。也就是说,在存在两个或多个历程(但它们可以是线程,也可以是程序中的简单函数)的情况下,一个历程继承实行,直到实行外部调用,将实行传递给另一个历程以获取服务、盘算或任何其他操纵。另一个历程将被实行以完成其使命,然后将服务结果返回给同时待处置惩罚的初始历程。一旦得到必要的结果,初始历程将规复实行。
https://img2024.cnblogs.com/blog/3174021/202411/3174021-20241114203938344-1268454354.png
https://img2024.cnblogs.com/blog/3174021/202411/3174021-20241114203945862-1287158367.png
正如我们所猜测的那样,异步编程可以让我们在许多情况下发挥上风,在这些情况下,我们会浪费大量时间期待必要外部相应或较长的实行时间的操纵。因此,假如想充分使用并行编程的全部潜力,就必须对这两种模式洞若观火。
至于它的实际应用,虽然对我们来说还不完全直观,但它是完全可行的。全部编程语言都有内部机制来实现它们。我们将在第 6 章 “使用 CUDA 实现 GPU 编程性能最大化 ”中深入介绍异步编程。
1.5.8 Map和reduce
并行编程中广泛使用的一种方案是 Map-Reduce,它重要基于两个阶段:
[*]Map
[*]Reduce
第一个阶段,即映射阶段,是将程序要实行的使命细分为几个部分(使命),然后将它们分配给不同的历程,由这些历程同时实行,即并行实行。通常情况下,每个历程的实行都会产生一个结果。因此,除了与并行实行严格相干的阶段外,还会有一个后续阶段,即必须将全部结果重新组合在一起的还原阶段。
https://img2024.cnblogs.com/blog/3174021/202411/3174021-20241114204202571-735941442.png
1.5.9 CPU 绑定和 I/O 绑定操纵
不过,在并行程序的筹划阶段,必须关注各个使命,评估其中是否有一些使命必要太长的实行时间。假如出现这种情况,就会导致性能降落,因为全部其他历程都在期待完成映射阶段。究竟上,要进入还原阶段,就必要每个历程得到的全部结果。
https://img2024.cnblogs.com/blog/3174021/202411/3174021-20241114204511719-32739885.png
因此,在这些情况下,我们必须考虑在每个历程(使命)中实行的各种操纵。这些使命可能包括读取文件或调用外部网络服务等内部操纵。在这种情况下,历程必须期待外部设备的相应,因此实行时间可能无法预测。这类操纵被称为 I/O 束缚。而只涉及 CPU 内部盘算的操纵则称为 CPU 绑定。
在并行编程中,当处置惩罚子使命或 CPU 绑定操纵时,使用多个历程并行实行指令可提高程序的效率。但在 I/O 绑定的情况下,我们必须采用不同的工作方式。
在这种情况下,最合适的编程方式就是并发编程,这就是线程发挥作用的地方。在历程中,我们可以创建多个线程。其中一个线程将继承处置惩罚 CPU 绑定操纵,而其他线程将处置惩罚各种 I/O 绑定操纵。当其中一个包含绑定 I/O 操纵的线程期待数据或来自外部的相应时,其他线程将继承实行其操纵。
在这种情况下,通过并发运行线程,我们可以节省实行时间:
https://img2024.cnblogs.com/blog/3174021/202411/3174021-20241114204653770-1219457234.png
上图除了主线程(在历程中始终存在)外,创建一个额外的线程可以单独管理(异步或同步)I/O 绑定操纵,同时允许主线程继承进行数据处置惩罚。
1.5.10 并行编程中的其他注意事项
在处置惩罚并行编程时,使用线程时仍须特别注意共享数据的管理。如图 1.17 所示,究竟上,历程中的线程既有自己的独立内存(其他线程无法访问),也有共享内存空间,其中的对象可供全部线程访问:
https://img2024.cnblogs.com/blog/3174021/202411/3174021-20241114204803210-1561049718.png
尽管在使用多线程的 Python 解释器中存在 GIL,但假如不想陷入数据不同等的问题,仍有必要锁定共享内存空间中的全局对象。但是,假如 GIL 包管在一个历程中一次只实行一个线程,这怎么可能呢?
究竟上,解释器只负责 Python 的内部对象,至于我们在程序实行过程中定义和创建的对象,将不会有控制或锁,而是独立管理。我们必要管理我们创建的全局对象的锁,以确保我们不会得到意想不到的结果。
在这方面,我们很快就会看到,Python 尺度库中有一些模块,除了实现历程,特别是线程外,还提供了一系列工具,让我们也能管理全局对象的锁。
1.5.11 Threading和multiprocessing 模块
在实际实行过程中,我们可以使用尺度库提供的两个模块:threading和multiprocessing。这些模块在 Python 中提供了一组函数,用于与操纵系统接口,用 Python 创建、实行和管理历程和线程。
注意:Python 没有专门的多线程模块,它不像历程那样被称为多线程,因为 Python 实际上不是多线程的,而是一次只能实行一个线程。
threading模块为 _thread 模块提供了一个抽象层,而 _thread 模块是一个底层模块,它提供了处置惩罚多个线程的原语。别的,它还提供了一系列工具,帮助程序员完成管理线程等并发系统的艰巨使命:锁、条件和 Semaphores。下一章 “构建多线程程序 ”将深入介绍该模块的功能和这些工具,并提供一系列示例代码,帮助你相识如何以及何时使用这些工具。
另一方面,多处置惩罚模块提供了一个有效的应用程序接口,用于实现基于历程的并行性。除了创建和管理历程外,该模块还提供了大量有助于管理程序中多个历程共存的功能。例如,队列(Queue)和管道(Pipe)是允许在不同历程间互换信息(对象)的对象,大概是简化同时管理多个历程的池。别的,该模块及其功能将在第 3 章 “使用多历程和 mpi4py 库 ”中进行广泛讨论。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]