用于并行调用用户定义函数的模块

时间:2013-02-22 18:59:41

标签: python multithreading parallel-processing multiprocessing

我写了一个irc机器人,当它被告知时会运行一些命令,这些命令是预定义的python函数,将在运行机器人的服务器上调用。

我必须在不确切知道他们会做什么的情况下调用这些功能 (更多的I / O或计算上昂贵的东西,因为我接受它们时我会查看它们没什么害处),但是我需要获得它们的返回值才能回复irc通道。

您建议使用哪个模块并行运行其中几个回调?为什么?

threadingmultiprocessing模块,还有什么?

我听说过扭曲,但我不知道它在我当前的实现中是如何适合的,因为我对它一无所知,并且从协议的角度来看机器人是完全正常的。

还要求命令以异步方式执行操作不是一种选择,因为我希望机器人可以轻松扩展。

2 个答案:

答案 0 :(得分:2)

您的问题没有明确的答案:它实际上取决于函数的功能,调用次数以及您需要的并行级别。

threadingmultiprocessing模块以完全不同的方式工作。

threading在Python解释器中实现本机线程:由于Python的全局解释器锁(GIL),创建起来相当便宜,但并行性有限。线程共享相同的地址空间,因此可能会相互干扰(例如,如果线程导致解释器崩溃,所有线程,包括您的应用程序死亡),但线程间通信因此便宜且快速。

multiprocessing使用不同的进程实现并行:设置比线程(需要创建新进程)昂贵得多,但每个进程都运行自己的解释器副本(因此没有与GIL相关的锁定问题)和在不同的地址空间中运行(隔离您的主应用程序)。子进程通过IPC通道与父进程通信,并且所需的Python对象被pickle / unpickled - 所以再次,比线程更昂贵。

您需要弄清楚哪种权衡最适合您的目的。

答案 1 :(得分:2)

首先,tl; dr:

如果您使用的是3.2+,请使用concurrent.futures;如果您使用的是2.x,请使用PyPI上的futures模块向后移动相同内容。

您可以使用ThreadPoolExecutor编写代码,并将其切换为ProcessPoolExecutor作为单行更改。 API非常简单,没有什么可以让人感到困惑的。


  

还要求命令以异步方式执行操作不是一种选择,因为我希望机器人可以轻松扩展。

我不知道如何。没有任何关于异步代码使其不易扩展。当然,你必须知道如何编写异步代码才能扩展它,但是成千上万的新手JS程序员每天都在做一个几乎可以接受的工作,Python使它变得更容易(参见monocletwisted中的inlineCallbackstulip等。此外,您在描述中明确将这些内容称为“回调”这一事实意味着您已经在考虑这些术语......

如果您确信这实际上是一项要求,那么twisted是不可接受的。但是gevent(和eventlet等)可能是 - 您可以编写看起来完全同步的代码,并且它可以异步运行。

下一步:

  

您建议使用哪个模块并行运行其中几个回调?为什么?

您是否真的需要并行运行它们(您可以利用多个内核同时运行多个CPU绑定的作业),同时运行(长时间运行的作业不会阻止其他作业),或者两者都没有(只要作业完成,它们是并行化,交错化还是序列化都无关紧要?)

如果您需要并行性,则需要multiprocessing。真的没有办法解决这个问题; GIL将阻止您在单个进程中使用多个核心。

如果您只需要并发,则可以使用threadingmultiprocessing。进程可能意味着Windows和Unix(甚至有时在Unix之间)之间的开销和/或更多可移植性问题,并且它有时会迫使您考虑如何传递数据 - 或者,如果必须,可以共享它。另一方面,通过 not 强制您考虑传递或共享数据,线程使得更容易意外地创建种族和其他错误。 (有关权衡的更多信息,请参阅isedev的最佳答案。)

如果您不需要,可以使用gevent(或类似内容),threadingmultiprocessing。您可以像创建几百个线程或进程一样轻松地创建和切换10000个绿色线程,并且开销更少。但是,单个长时间运行的CPU绑定命令可能会停止整个系统。


无论你使用哪一个,你最有可能想要使用一个greenlet,线程或进程池从队列中拉出命令(而不是为每个命令分离一个新命令,或者构建更复杂的东西)。

虽然multiprocessing内置了这样的内容,但threading却没有。 (实际上,基于threading的线程池 - 但它位于multiprocessing,而不是threading。并且它不是公共API的一部分。)

multiprocessing中有很多非常棒的东西,如果你需要它,一定要使用它。 (还有一些第三方库,其中包含更酷的东西,这可以使复杂的用例变得更加容易,或者做multiprocessing不能做的事情。)但如果没有,{{1更简单,并且能够使用线程和进程测试同一系统并进行单线程更改(或者甚至在运行时非常简单地执行)非常好。