Python 多进程的 Pool 进程限制

57

在使用multiprocessing模块中的Pool对象时,进程数量是否受CPU核心数限制?例如,如果我有4个核心,即使我创建了一个包含8个进程的池,也只会同时运行4个进程吗?


5
您可以创建的进程数量没有限制,但是从某个数量开始,使用多个进程的效果会转变为惩罚。这种数量的大小很大程度上取决于线程将要执行的任务; 如果只有处理器在工作,那么您不应该启动超过处理器支持的线程数量的进程(例如i7 4核处理器具有8个线程)。 - poke
2
Linux(用户/系统)进程的限制在/etc/security/limits.conf中定义。 - Back2Basics
4个回答

62

您可以请求任意数量的进程。可能存在的任何限制都将由您的操作系统强制执行,而不是由multiprocessing强制执行。例如:

您可以随时使用multiprocessing模块来创建任意数量的进程,并且该模块将根据您的计算机硬件自动管理这些进程。请注意,您的操作系统可能会对进程的数量进行一些限制,这主要取决于您的计算机硬件和运行程序的方式。

 p = multiprocessing.Pool(1000000)

在任何机器上都可能会遭受丑陋的死亡。当我打字时,我正在尝试在我的电脑上运行它,操作系统正在疯狂地交换内存,磁盘也被磨损得粉碎——在创建了约3000个进程之后终于杀死了它;

至于“同时”运行多少程序,Python 对此没有发言权。这取决于:

  1. 硬件同时运行程序的能力;和
  2. 您的操作系统如何分配硬件资源给当前正在运行的所有进程。

对于 CPU-bound 任务来说,在你有核心可供运行时,创建多于核心数的 Pool 进程是没有意义的。如果你还想在机器上做其他事情,那么应该创建比核心数更少的进程。

对于 I/O-bound 任务,创建比核心数多得多的 Pool 进程可能是有意义的,因为进程可能会花费大部分时间阻塞(等待 I/O 完成)。


请记住,进程是由os.fork产生的,因此将涉及父进程内存占用的副本。在某些操作系统中,这可能是写时复制,但通常情况下,如果想要利用大量的“单元”来执行可以异步处理以避免阻塞的任务,则线程通常比进程更适合作为异步的“单元”(但并非总是如此)。即使有GIL,执行GIL释放操作的线程也可以从中受益。 - ely
使用更多的进程可能会导致内存泄漏吗?multiprocessing.cpu_count()在我的系统上返回16,我正在使用8(cpu_count // 2)。 - bruvio
你的操作系统需要为每个创建的进程分配RAM。这不是“泄漏”:当你创建一个进程时,你正在“强制”操作系统使用那些RAM。在任何现代计算机上,8个进程应该是微不足道的。 - Tim Peters

39

是的。从理论上讲,您可以创建无限数量的进程,但是同时启动过多的进程会因为内存耗尽而导致系统崩溃。请注意,进程占用的空间比线程要大得多,因为它们不使用彼此之间的共享空间,而是为每个进程使用一个独立的空间。

因此,最好的编程实践是使用信号量,将其限制在系统处理器数量的范围内。

pool = multiprocessing.Semaphore(4) # no of cpus of your system.

如果您不知道自己系统的核心数,或者希望在多个系统中使用代码,则下面这样的通用代码就可以了...

pool = multiprocessing.Semaphore(multiprocessing.cpu_count()) 
#this will detect the number of cores in your system and creates a semaphore with that  value.  

附注:但通常使用核心数减一会更好。

希望这能帮到您 :)


16

虽然您可以设置无限制,但如果您想了解用于CPU限制进程的方便数字(我猜您在这里寻找),则可以运行以下命令:

>>> import multiprocessing
>>> multiprocessing.cpu_count()
1

这里有一篇答案详细说明了(尤其是在Linux上)多进程的限制:


11

没错。如果你有4个核心,那么就可以同时运行4个进程。记住会有一些系统工作需要处理,最好定义进程数为 number_of_cores - 1 。这是一种偏好,而不是强制性要求。每个创建的进程都有开销,所以实际上需要更多的内存来完成这项任务。但是如果内存不成问题,那就继续使用吧。如果你正在运行Cuda或其他基于GPU的库,则有一个不同的范例,但这是另一个问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接