当前位置:  开发笔记 > 编程语言 > 正文

在Python中的子进程,多处理和线程之间做出决定?

如何解决《在Python中的子进程,多处理和线程之间做出决定?》经验,为你挑选了3个好方法。

我想并行化我的Python程序,以便它可以在运行它的机器上使用多个处理器.我的并行化非常简单,因为程序的所有并行"线程"都是独立的,并将它们的输出写入单独的文件.我不需要线程来交换信息,但是我必须知道线程何时完成,因为我的管道的某些步骤依赖于它们的输出.

可移植性很重要,因为我希望在Mac,Linux和Windows上运行任何Python版本.鉴于这些约束,哪个是最适合实现它的Python模块?我试图在线程,子进程和多处理之间做出决定,这些都似乎提供了相关的功能.

有什么想法吗?我想要最简单的便携式解决方案.



1> Jim Dennis..:

对我来说这实际上非常简单:

选项:

subprocess用于运行其他可执行文件 ---它基本上是一个包装周围os.fork()os.execve()与任选的管道的一些支持(设置管道和从所述子进程.(显然其他进程间通信(IPC)机制,例如插座,SysV的共享存储器和可以使用消息队列---但是您将被限制为您正在调用的程序支持的任何接口和IPC通道.

通常一个subprocess同步使用---简单地调用一些外部实用程序并读回其输出或等待其完成(可能从临时文件中读取其结果,或者在将它们发布到某个数据库之后).

但是,可以生成数百个子进程并轮询它们.我个人最喜欢的实用程序就是这样做的. 最大的缺点了的subprocess模块,它的I/O支持通常是封锁.有一个PEP-3145草案可以修复Python 3.x的某个未来版本以及另一个asyncproc(警告,它可以直接下载,而不是任何类型的文档或自述文件).我还发现直接导入fcntl和操作PopenPIPE文件描述符相对容易- 虽然我不知道这是否可以移植到非UNIX平台.

subprocess 几乎没有事件处理支持 ...... 虽然你可以使用signal模块和普通的老式UNIX/Linux信号 - 轻轻地杀死你的进程,就像它一样.

多处理选项:

multiprocessing对现有的(Python)的代码中运行的功能,可支持这个家庭的过程中更加灵活的通信.特别是最好尽可能multiprocessing围绕模块的Queue对象构建IPC ,但是您也可以使用Event对象和各种其他功能(其中一些功能可能是mmap基于支持足够的平台上的支持而构建的).

Python的multiprocessing模块旨在提供非常类似的 接口和功能,threading同时允许CPython在多个CPU /核心之间扩展处理,尽管GIL(全局解释器锁定).它利用了操作系统内核开发人员完成的所有细粒度SMP锁定和一致性工作.

线程选项:

threading适用于I/O限制的相当窄范围的应用程序(不需要跨多个CPU核心扩展),并且受益于线程切换(具有共享核心内存)与进程/的极低延迟和切换开销上下文切换.在Linux上,这几乎是空集(Linux进程切换时间非常接近其线程切换).

threading在Python中两个主要的缺点.

当然,其中一个是特定于实现的 - 主要影响CPython.这就是GIL.在大多数情况下,大多数CPython程序不会受益于两个以上CPU(内核)的可用性,并且性能通常会受到 GIL锁定争用的影响.

不是特定于实现的更大问题是线程共享相同的内存,信号处理程序,文件描述符和某些其他OS资源.因此,程序员必须非常小心对象锁定,异常处理和其代码的其他方面,这些方面既微妙又可以杀死,停止或死锁整个进程(线程套件).

相比之下,multiprocessing模型为每个进程提供了自己的内存,文件描述符等.其中任何一个中的崩溃或未处理的异常只会杀死该资源,并且可以比调试,隔离更加容易地处理子进程或兄弟进程的消失.并修复或解决线程中的类似问题.

(注意:使用threading主要的Python系统,比如NumPy,可能会受到GIL争用的影响,因此大多数自己的Python代码都会受到影响.那是因为他们已经专门设计了这样做).

扭曲的选项:

同样值得注意的是,Twisted提供了另一种既优雅又难以理解的替代方案.基本上,冒着过度简化的风险,Twisted的粉丝可能会用干草叉和火把冲击我的家,Twisted在任何(单个)过程中提供和事件驱动的合作多任务.

要理解这是如何可能的,应该阅读select()(可以围绕select()poll()或类似的OS系统调用构建的功能).基本上,它都是由操作系统的请求在文件描述符列表中的任何活动或某些超时之前进行休眠的能力驱动的.

从这些调用中唤醒select()是一个事件 - 要么涉及在某些套接字或文件描述符上可用(可读)的输入,要么缓冲空间在某些其他(可写)描述符或套接字上变得可用,某些异常条件(TCP)例如,带外PUSH包,或TIMEOUT.

因此,Twisted编程模型是围绕处理这些事件而构建的,然后在生成的"主"处理程序上循环,允许它将事件分派给处理程序.

我个人认为这个名称,Twisted是编程模型的唤起......因为从某种意义上说,你对这个问题的处理方式必须"扭曲".您不是将程序视为对输入数据和输出或结果的一系列操作,而是将程序编写为服务或守护程序,并定义它对各种事件的反应.(实际上,Twisted程序的核心"主循环"是(通常?总是?)a reactor().

使用Twisted主要挑战包括围绕事件驱动模型扭曲思维,并避免使用任何未编写为在Twisted框架内协作的类库或工具包.这就是为什么Twisted提供自己的模块用于SSH协议处理,curses,以及它自己的子进程/ popen函数,以及许多其他模块和协议处理程序,乍一看似乎会复制Python标准库中的东西.

我认为即使您从未打算使用它,在概念层面理解Twisted也很有用.它可以深入了解线程,多处理甚至子进程处理中的性能,争用和事件处理,以及您进行的任何分布式处理.

(注意:较新版本的Python 3.x包括asyncio(异步I/O)功能,如async def,@ async.coroutine装饰器和await关键字,以及未来支持的产量.所有这些大致类似于从过程(合作多任务)角度扭曲).

分布选项:

另一个你没有问及但是值得考虑的处理领域是分布式处理.有许多用于分布式处理和并行计算的Python工具和框架.就个人而言,我认为最容易使用的是最不常被认为是在那个空间中的那个.

围绕Redis构建分布式处理几乎是微不足道的.整个密钥库可用于存储工作单元和结果,Redis LIST可用作Queue()类似对象,PUB/SUB支持可用于类似Event处理.您可以散列密钥并使用值,在Redis实例的松散集群中进行复制,以存储拓扑和散列令牌映射,以提供一致的散列和故障转移,以便扩展超出任何单个实例的容量,从而协调您的工作人员和编组数据(pickled,JSON,BSON或YAML).

当然,当您开始围绕Redis构建更大规模和更复杂的解决方案时,您正在重新实现许多已经使用Celery解决的功能,Apache Spark和Hadoop,Zookeeper,etcd,Cassandra等.这些alll具有用于Python访问其服务的模块.

[更新:如果您考虑使用Python跨分布式系统进行计算密集型操作,需要考虑几种资源:IPython Parallel和PySpark.虽然这些是通用的分布式计算系统,但它们是特别易于访问和流行的子系统数据科学和分析].

结论

在那里,您可以处理Python的替代方案,从单线程,简单的同步调用到子流程,轮询子流程池,线程和多处理,事件驱动的协作多任务,再到分布式处理.


@Tjorriemorrie:我猜你的意思是,很难将方法调用分派给可能在其他进程中的对象实例.我建议这与你的线程有同样的问题,但更容易看到(而不是脆弱,并受到模糊的竞争条件).我认为推荐的方法是通过Queue对象安排所有这样的调度,这些对象可以在单线程,多线程和跨进程中工作.(使用一些Redis或Celery Queue实现,甚至跨越一组节点)
这是一个非常好的答案.我希望在Python3文档中引入并发性.

2> Eric O Lebig..:

multiprocessing是一种伟大的瑞士军刀型模块.它比线程更通用,因为您甚至可以执行远程计算.因此,这是我建议您使用的模块.

subprocess模块还允许您启动多个进程,但我发现它比新的多处理模块使用起来不太方便.

线程是众所周知的微妙,并且,使用CPython,你通常只限于一个核心(尽管如其中一条评论中所述,全局解释器锁(GIL)可以在从Python代码调用的C代码中发布) .

我相信您引用的三个模块的大多数功能都可以以独立于平台的方式使用.在可移植性方面,请注意,multiprocessing自Python 2.6以来只有标准版本(但是某些旧版本的Python版本确实存在).但这是一个很棒的模块!



3> kriss..:

在类似的情况下,我选择了单独的进程和通过网络套接字的一点点必要的通信.它是高度可移植的,并且使用python非常简单,但可能不是更简单(在我的情况下,我还有另一个约束:与用C++编写的其他进程的通信).

在你的情况下,我可能会去多进程,因为python线程,至少在使用CPython时,不是真正的线程.好吧,它们是本机系统线程,但是从Python调用的C模块可能会也可能不会释放GIL并允许其他线程在调用阻塞代码时运行.

推荐阅读
mobiledu2402851373
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有