1

我有一个函数可以进行计算并将计算状态保存在result字典中(默认默认参数)。我首先运行它,然后使用多处理模块运行几个进程。我需要在每个并行进程中再次运行该函数,但是在该函数运行一次后,我需要返回缓存状态,不得重新计算该值。这个要求在我的例子中没有意义,但我想不出一个简单的现实论点需要这个限制。使用 dict 作为可变默认参数有效,但这不适用于多处理模块。我可以使用什么方法来获得相同的效果?

请注意,状态值是不能作为参数 afaik 传递给多个进程的东西(包含类值的字典)。

SO问题Python多处理:如何在多个进程之间共享一个字典?似乎涵盖了类似的领域。也许我可以使用 Manager 来做我需要的事情,但如何做并不明显。或者,可以根据https://stackoverflow.com/a/4534956/350713将值保存到全局对象,但这似乎不太优雅。

def foo(result={}):
    if result:
        print "returning cached result"
        return result
    result[1] = 2
    return result

def parafn():
    from multiprocessing import Pool
    pool = Pool(processes=2)
    arglist = []
    foo()
    for i in range(4):
        arglist.append({})
    results = []
    r = pool.map_async(foo, arglist, callback=results.append)
    r.get()
    r.wait()
    pool.close()
    pool.join()
    return results

print parafn()

更新:感谢您的评论。我现在有一个工作示例,发布在下面。

4

2 回答 2

1

我认为在进程之间交换数据最安全的方式是使用队列,多处理模块为您带来 2 种类型的队列和 JoinableQueue,请参阅文档:

http://docs.python.org/library/multiprocessing.html#exchangeing-objects-between-processes

于 2012-09-30T17:06:53.833 回答
1

此代码不会赢得任何美容奖,但对我有用。此示例类似于问题中的示例,但有一些细微的变化。这个add_to_d结构有点尴尬,但我没有看到更好的方法来做到这一点。

简要总结:我将foo's的状态d(这是一个可变的默认参数)复制回foo,但foo在池创建的新进程空间中。一旦这样做了,那么foo在新的进程空间中将不会重新计算缓存的值。似乎这就是池初始化程序所做的,尽管文档不是很明确。

class bar(object):
    def __init__(self, x):
        self.x = x
    def __repr__(self):
        return "<bar "+ str(self.x) +">"

def foo(x=None, add_to_d=None, d = {}):
    if add_to_d:
        d.update(add_to_d)
    if x is None:
        return
    if x in d:
        print "returning cached result, d is %s, x is %s"%(d, x)
        return d[x]
    d[x] = bar(x)
    return d[x]

def finit(cacheval):
    foo(x=None, add_to_d=cacheval)

def parafn():
    from multiprocessing import Pool
    arglist = []
    foo(1)
    pool = Pool(processes=2, initializer=finit, initargs=[foo.func_defaults[2]])
    arglist = range(4)
    results = []
    r = pool.map_async(foo, iterable=arglist, callback=results.append)
    r.get()
    r.wait()
    pool.close()
    pool.join()
    return results

print parafn()
于 2012-10-02T04:29:51.593 回答