Python多处理:不使用单独的内存空间?

问题描述 投票:2回答:3

根据我的理解,multiprocessing在Linux上使用fork,这意味着multiprocessing创建的每个进程都有自己的内存空间,并且内部进行的任何更改都不会影响其他forked进程。

但我遇到了这种相当奇怪的情况:

import multiprocessing

i = -1

def change(j):
    global i
    print(i, end=" ")  # should print -1
    i = j 

with multiprocessing.Pool(20) as p:
    p.map(change, range(20))

print(i)  # should print -1

我认为这个程序将打印正好21个-1,因为multiprocessing创建了20个独立的子进程,其内存空间不共享,这意味着行i = j不会影响任何其他进程中i的值;因此在印刷时i = -1

然而,该程序实际上打印了-1和0到19之间随机数量的混合。

例:

-1 -1 -1 -1 -1 4 -1 5 -1 6 -1 8 -1 -1 14 -1 -1 12 -1 -1 -1

所以我的问题是,为什么我没有得到21个-1

python python-3.x multiprocessing
3个回答
3
投票

Python 3.2引入了maxtasksperchild

Maxtasksperchild是工作进程在退出之前可以完成的任务数,并替换为新的工作进程,以释放未使用的资源。默认的maxtasksperchild是None,这意味着工作进程将与池一样长。

import multiprocessing

i = -1

def change(j):
    global i
    print(i, end=" ")  # should print -1
    i = j 

if __name__ == '__main__':
    with multiprocessing.Pool(20, maxtasksperchild=1) as p:
        p.map(change, range(20))
    print(i)  # should print -1

1
投票

Multiprocessing.Pool不保证每个任务都将在新进程中运行。实际上,您使用multiprocessing.Pool的原因是用于创建新进程的成本被认为是昂贵的任务,因此您希望使用进程池来避免该进程创建开销。多处理的典型使用模式.Pool是您创建了大量任务,然后创建了一个包含少量工作人员的池(通常取决于您的计算机具有的CPU核心数),池将计划任务给工作人员和尽可能重用过程。如果要始终启动新进程,则应使用multiprocessing.Process。


1
投票

这是一个常见的误解,它不会,但Pool(20)将立即创建20个流程。事实上,即使处理程序线程开始之前,这些进程都将启动,这将把任务提供给inqueue,以便稍后由工作人员处理。

这些过程运行multiprocessing.pool.worker代码,直到他们从.get()来到inqueue。只是并非所有人都需要重新安排在短时间内从共享队列中获取任务。队列读取是顺序的,一次只能有一个进程从中读取。有些进程会发生多个任务而其他进程没有进行调度,因为您的操作系统会在内核上运行不同的操作。当您看到除-1之外的其他值时,进程会在此处获得多个任务。

© www.soinside.com 2019 - 2024. All rights reserved.