python中使用池的多处理:关于同时使用相同名称的几个实例

python中使用池的多处理:关于同时使用相同名称的几个实例,python,memory,multiprocessing,pool,Python,Memory,Multiprocessing,Pool,我对多重处理有点陌生。但是,假设我们有一个如下的程序。该计划似乎运作良好。现在来回答问题。在我看来,我们将同时拥有4个同名(a)的somekintofclass)实例。这怎么可能?此外,这种编程是否存在潜在风险 from multiprocessing.dummy import Pool import numpy from theFile import someKindOfClass n = 8 allOutputs = numpy.zeros(n) def work(index):

我对多重处理有点陌生。但是,假设我们有一个如下的程序。该计划似乎运作良好。现在来回答问题。在我看来,我们将同时拥有4个同名(
a
)的
somekintofclass
)实例。这怎么可能?此外,这种编程是否存在潜在风险

from multiprocessing.dummy import Pool
import numpy
from theFile import someKindOfClass

n = 8 
allOutputs = numpy.zeros(n)

def work(index):   
    a = SomeKindOfClass()
    a.theSlowFunction()
    allOutputs[index] = a.output

pool = Pool(processes=4) 
pool.map(work,range(0,n))

名称
a
仅在
work
函数的作用域中是局部的,因此此处没有名称冲突。在内部,python将使用唯一标识符跟踪每个类实例。如果要检查此项,可以使用
id
功能检查对象id:

print(id(a))

我看不出您的代码有任何问题。

您可以在工作池中声明类实例,因为每个实例在内存中都有一个单独的位置,所以它们不会冲突。问题是,如果您首先声明一个类实例,然后尝试将该实例传递给多个池工作者。然后,每个工作进程都有一个指向内存中相同位置的指针,它将失败(这是可以处理的,但不是这样)

基本上,池工作者在任何地方都不能有重叠的内存。只要工作人员不尝试在某处共享内存,或执行可能导致冲突的操作(如打印到同一文件),就不会有任何问题


确保它们应该做的任何事情(例如,您希望打印到文件或添加到某个更广泛的名称空间中的事情)都会在最后作为结果返回,然后进行迭代。

如果您使用的是多处理,您不必担心-该过程不会共享内存(默认情况下)。所以,有几个类的
某类的独立的对象是没有任何风险的,每个对象都将生活在自己的过程中。它是如何工作的?Python运行您的程序,然后运行4个子进程。这就是为什么在
pool.map(work,range(0,n))
之前进行
的构建非常重要。否则,您将收到进程创建的无限循环


问题可能是,如果
SomeKindOfClass
将状态保留在磁盘上,例如,将某些内容写入文件或读取它。

实际上,您将拥有
SomeKindOfClass
8个实例(每个工作人员一个),但同时只有4个实例处于活动状态

multiprocessing
vs
multiprocessing.dummy
只有继续使用
多处理.dummy
模块,程序才能工作,该模块只是
线程化
模块的包装器。您仍然在使用“python线程”(而不是单独的进程)。“Python线程”共享相同的全局状态;“过程”则不然。Python线程也共享相同的GIL,因此它们仍然被限制为一次运行一条Python字节码语句,这与进程不同,进程可以同时运行Python代码

如果要将导入从多处理导入池更改为
,您会注意到
alloutput
数组在所有worker完成执行后保持不变(而且,您可能会得到一个错误,因为您正在全局范围内创建池,您可能应该将其放在
main()中)
功能)。这是因为
多处理
在创建新进程时会创建整个全局状态的新副本。当工作者修改全局
alloutput
时,它将修改该初始全局状态的副本。当进程结束时,不会向主进程返回任何内容,并且主进程的全局状态将保持不变

进程间共享状态 与线程不同,进程不共享相同的内存

如果要在进程之间共享状态,必须显式声明共享变量并将其传递给每个进程,或者使用管道或其他方法允许工作进程彼此通信或与主进程通信

有几种方法可以做到这一点,但最简单的方法可能是使用
Manager

import multiprocessing

def worker(args):
    index, array = args
    a = SomeKindOfClass()
    a.some_expensive_function()
    array[index] = a.output


def main():
    n = 8
    manager = multiprocessing.Manager()
    array = manager.list([0] * n)
    pool = multiprocessing.Pool(4)
    pool.map(worker, [(i, array) for i in range(n)])
    print array