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

Python多处理:不使用单独的内存空间?,python,python-3.x,multiprocessing,Python,Python 3.x,Multiprocessing,据我所知,multi-processing在Linux上使用fork,这意味着由multi-processing创建的每个进程都有自己的内存空间,其中所做的任何更改都不会影响其他forked进程 但我遇到了一个相当奇怪的情况: import multiprocessing i = -1 def change(j): global i print(i, end=" ") # should print -1 i = j with multiprocessing.Po

据我所知,
multi-processing
在Linux上使用
fork
,这意味着由
multi-processing
创建的每个进程都有自己的内存空间,其中所做的任何更改都不会影响其他
fork
ed进程

但我遇到了一个相当奇怪的情况:

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
,因为
多处理
创建了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

多处理。池不能保证每个任务都将在新进程中运行。事实上,您使用multiprocessing.Pool的原因是创建新流程的成本被认为是昂贵的任务,因此您希望使用流程池来避免流程创建开销。多处理.Pool的典型使用模式是创建大量任务,然后创建一个包含少量工作进程的池(通常取决于计算机的CPU核数),该池将任务安排给工作进程,并在可能的情况下重用进程。如果您希望始终启动一个新进程,那么应该使用multiprocessing.process。

引入了Python 3.2

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

通常错误地认为它不会,但是
Pool(20)
会立即创建20个进程。事实上,所有进程都将在处理程序线程启动之前启动,这将把任务送入
inqueue
,稍后由工作人员处理

进程运行
multiprocessing.pool.worker
-code,直到它们从
inqueue
到达
.get()
。只是,并不是所有人都会在所有人都需要的短时间内重新安排从共享队列获取任务的时间。队列读取是连续的,一次只能从中读取一个进程。由于操作系统在内核上运行的内容不同,一些进程会碰巧获得多个任务,而另一些进程则没有计划。当一个进程在这里获得多个任务时,您会看到除
-1

以外的其他值。尽管您使用
池(20)
,但在需要它之前,它不会真正创建20个进程。这意味着某些任务可能会在同一流程中执行。您可以打印出
os.getpid()
进行检查。