python中池的多处理:关于多个同名实例在同一时刻

2024-04-16 19:53:12 发布

您现在位置:Python中文网/ 问答频道 /正文

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

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))

Tags: 实例fromimport程序numpyindex编程work
3条回答

{{{cd2}实际上,每个

multiprocessingmultiprocessing.dummy

只有继续使用multiprocessing.dummy模块,它只是threading模块的包装器,程序才会工作。您仍然在使用“python线程”(而不是单独的进程)Python线程“共享相同的全局状态”,“进程”不共享。Python线程也共享相同的GIL,因此它们仍然限于一次运行一个Python字节码语句,而进程则可以同时运行Python代码。在

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

进程间共享状态

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

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

有几种方法可以做到这一点,但最简单的方法可能是使用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

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

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

确保它们应该做的任何事情(比如你想打印到文件中,或者添加到某个更大的命名空间中)都会在最后返回结果,然后进行迭代。在

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

print(id(a))

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

相关问题 更多 >