17

我正在使用 python 的多处理库中的 Pool 类编写一个将在 HPC 集群上运行的程序。

这是我正在尝试做的事情的抽象:

def myFunction(x):
    # myObject is a global variable in this case
    return myFunction2(x, myObject)

def myFunction2(x,myObject):
    myObject.modify() # here I am calling some method that changes myObject
    return myObject.f(x)

poolVar = Pool()
argsArray = [ARGS ARRAY GOES HERE]
output = poolVar.map(myFunction, argsArray)

函数 f(x) 包含在 *.so 文件中,即它正在调用 C 函数。

我遇到的问题是每次运行程序时输出变量的值都不同(即使函数 myObject.f() 是确定性函数)。(如果我只有一个进程,那么每次运行程序时输出变量都是相同的。)

我尝试创建对象而不是将其存储为全局变量:

def myFunction(x):
    myObject = createObject()
    return myFunction2(x, myObject)

然而,在我的程序中,对象的创建是昂贵的,因此,创建一次 myObject 然后在每次调用 myFunction2() 时修改它要容易得多。因此,我不想每次都创建对象。

你有什么建议吗?我对并行编程很陌生,所以我可能会做错这一切。我决定使用 Pool 类,因为我想从简单的东西开始。但我愿意尝试更好的方法。

4

1 回答 1

32

我正在使用 python 的多处理库中的 Pool 类在 HPC 集群上进行一些共享内存处理。

进程不是线程!不能简单地替换ThreadProcess并期望所有人都以相同的方式工作。Processes共享内存,这意味着全局变量被复制,因此它们在原始进程中的值不会改变。

如果要在进程之间使用共享内存,则必须使用multiprocessing的数据类型,例如Value, Array,或使用Manager来创建共享列表等。

特别是您可能对Manager.register允许Manager创建共享自定义对象的方法感兴趣(尽管它们必须是可挑选的)。

但是我不确定这是否会提高性能。由于进程之间的任何通信都需要酸洗,而酸洗通常比简单地实例化对象需要更多时间。

请注意,您可以initializerinitargs创建Pool.

例如,以最简单的形式,在工作进程中创建一个全局变量:

def initializer():
    global data
    data = createObject()

用作:

pool = Pool(4, initializer, ())

然后工作函数可以data毫无顾虑地使用全局变量。


样式说明:永远不要为变量/模块使用内置名称。在您的情况下object是内置的。否则,您最终会遇到意想不到的错误,这些错误可能晦涩难懂且难以追踪。

于 2013-09-13T05:38:21.297 回答