资讯动态

Python多进程编程:解锁GIL全性能

发布时间:2026/8/21 21:40:35 来源:尧图企业网站定制
此篇文章是由翻译小组付出辛勤劳作全新翻译制作而成的, 其原本的撰写人是 , 负责翻译此项内容的是 , 并且经由编程领域创作人员 进行了仔细校对。就在昨天, 编程派已然推出了一篇有关多线程编程的指导章程, 借助这篇文章能够全面掌握多线程编程。该译者身份说明为, 其是成都信息工程大学计算机学院的一名学生, 其擅长的领域涵盖图像处理以及机器学习。最初于2.6版本加入的多进程()模块, 是由Jesse和在PEP 371当中进行定义的。由这个模块生成进程的方式, 跟你运用其他模块生成线程的那种方式为同样的情况。然而在这边, 由于你运用到的是多进程, 所以能够避开全局解释锁(GIL), 进而充分地借助机器多处理器所具备的优势。模块之中还含有一些, 模块所不具备的某些 API, 比如说, 存在一个精妙的 Pool 类, 它能够使你借助多个输入并行地去执行一个函数, 我们会在后续的章节里接触到 Pool, 我们会从模块的类着手进行介绍。入门一种类似于模块里的类的类别, 我们着手去构建那形成一系列调用一模一样函数的进程, 而后查看其究竟是以怎样的方式进行运转的:这个实例之中, 我们开展了导入 , 接着构建出一个 函数。于这个函数里头, 我们把接收到的数字增大为两倍。我们还借由 里的 os 模块获取到当下进程的 ID也就是 pid。这能够告知我们是哪一个进程在调用函数。代码底部的那个循环内, 我们创建起来一系列进程紧接着启动它们。最下面的那个循环于每一个进程之上调用了 join() 方法, 它会告诉 去等待进程完结。要是你想要终结一个进程, 你能够调用这个进程的相关) 方法。当运行这段代码的时候你将看到类似下边这样的输出5 to 10 by id: 1046810 to 20 by id: 1046915 to 30 by id: 1047020 to 40 by id: 1047125 to 50 by id: 10472偶尔之际, 使进程拥有那样一个具备可读性的名字会更具优势。所幸之是, 类能够支持为进程予以命名。让我们一同进行查看:这一回, 我们引入了某些别的事物。 与 模块之中的大体是相同的。我们借由它来获取正在唤起 函数的线程的称呼。你兴许留意到了, 我们先前的五个进程并未进行名字设置。第六个进程我们将其名字设定为”Test”。我们瞧一瞧所得到的输出:5 to 10 by: -210 to 20 by: -315 to 30 by: -420 to 40 by: -525 to 50 by: -62 to 4 by: Test输出呈现出这样的情况, 模块在默认状态下, 为每一个进程的名字赋予了一个数字, 当然, 我们所设置名字的那个进程, 不存在数字。有一个模块, 它和另一个模块是一样的, 这个模块同样支持“锁”。你所要做的事情是, 进行Lock这个操作, 去获取它, 在执行完相应操作之后, 再去将它释放掉。我们来瞧一瞧:在这里, 我们创建了个函数, 它能直接打印传递过来的任何事物。为避免线程被其他事务干扰, 我们运用了一个Lock对象。这段代码会遍历我们列表里的三项内容, 并且会分别为这些内容创建出一个进程。每个进程都会调用该函数, 还会将可迭代对象里的一个元素传入到函数之中。由于我们使用了锁, 所以后边的进程将会等待锁被释放之后才会接着执行。日志多进程所产生的日志跟多线程所产生的日志存在着一点差异, 缘由在于的包并不支持进程共享锁, 故而源自不同进程的日志有可能会相互混杂在一起, 我们试着在上边所提及的例子当中添加一个基础日志, 下边呈现如下代码:记录日志最为简便的方式是把所有的日志发送给 , 我们能够借助调用函数 予以达成, 而后我们调用 函数获取记录器, 并将日志级别设定为 INFO, 其余的代码和原先保持一致, 在此需加以说明的是, 我并未运用 join() 函数, 相反, 父线程于退出之际要明确地调用 join()。当你运行上边的代码会得到像下面这样的输出INFO/-1child self.run()tangoINFO/-1downINFO/-1with 0INFO/-2child self.run()INFO/downINFO/-2downINFO/-3child self.run()INFO/-2with 010INFO/join() for -3INFO/-3downINFO/-3with 0INFO/join() for -2这会儿你若是打算把日志留存至硬盘, 实际上还是存有一定复杂性的。你能够参照相关的官方示例。Pool 类用于表示一个工作进程池子的 Pool 类, 它有一些方法, 这些方法可以让你将任务分配给不同的工作进程, 我们看一下这个简单的例子:这里, 我们创建了一个Pool的实例, 接着告诉它去创建三个工作进程。随后, 我们运用map方法, 将一个函数以及一个可迭代对象映射到每一个进程上。最后, 我们打印出结果, 这里的结果呈现为一个列表。10, 20, 40我们同样可以通过 方法得到程序的结果采取这样的方式去做, 能够使我们获取到进程的结果, 关于此, get函数的功能正是如此。或许你会留意到, 我们增添了一个超时的设定举动, 这是意图用于防护我们所调用的函数泛起意外状况, 我们可不冀望它永久性地处于被阻塞的状态。进程通信要是打算让两个进程去进行通信, 模块给出了两个主要的方法, 和Pipes。Queue确保了线程以及进程的安全。另外一篇涉及线程的文章里同样容有一个Queue实现, 我们基于此来做些变动:我们得导入Queue, 接着创建两个函数, 一个函数用于创建数据并将其添加到队列之中, 另一个函数用来取出数据并对其进行处理。将数据添加到队列里头借助的是Queue的put()方法, 从队列取出数据用的是get()方法。那最后一段代码创建了一个队列对象还有若干进程, 并运行它们。可要注意啦, 我们调用join()方法是在进程对象上而非在Queue自身里。结束语讲了诸多内容于本文之中, 你已晓得怎样针对函数运用多进程, 通过队列达成进程间通信, 给线程予以命名等事情, 于 的正经文档里头还有好多内容在该本文内未被涉及到, 你也能够往更为深入这一路去钻研一番, 只不过当前你已经学会怎样借助 来运用你计算机的全部处理性能哒。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价