具有共享数据的Python多处理池

时间:2016-09-22 13:33:25

标签: python dictionary multiprocessing shared-memory

我正在尝试使用多处理来加速多变量定点迭代算法,但是,我正在运行处理共享数据的问题。我的解决方案向量实际上是一个命名字典而不是数字向量。矢量的每个元素实际上使用不同的公式计算。在高层次上,我有一个这样的算法:

current_estimate = previous_estimate
while True:
for state in all_states:
    current_estimate[state] = state.getValue(previous_estimate)
if norm(current_estimate, previous_estimate) < tolerance:
    break
else:
    previous_estimate, current_estimate = current_estimate, previous_estimate

我正在尝试将for循环部分与多处理并行化。 previous_estimate变量是只读的,每个进程只需要写入current_estimate的一个元素。我目前重写for循环的尝试如下:

# Class and function definitions
class A(object):
    def __init__(self,val):
        self.val = val

    # representative getValue function
    def getValue(self, est):
        return est[self] + self.val

def worker(state, in_est, out_est):
    out_est[state] = state.getValue(in_est)

def worker_star(a_b_c):
    """ Allow multiple arguments for a pool
        Taken from http://stackoverflow.com/a/5443941/3865495
    """
    return worker(*a_b_c)

# Initialize test environment
manager = Manager()
estimates = manager.dict()
all_states = []
for i in range(5):
     a = A(i)
     all_states.append(a)
     estimates[a] = 0

pool = Pool(process = 2)
prev_est = estimates
curr_est = estimates
pool.map(worker_star, itertools.izip(all_states, itertools.repeat(prev_est), itertools.repreat(curr_est)))

我目前遇到的问题是添加到all_states数组的元素与添加到manager.dict()的元素不同。尝试使用数组元素访问字典的元素时,我不断收到key value错误。调试时,我发现没有一个元素是相同的。

print map(id, estimates.keys())
>>> [19558864, 19558928, 19558992, 19559056, 19559120]
print map(id, all_states)
>>> [19416144, 19416208, 19416272, 19416336, 19416400]

1 个答案:

答案 0 :(得分:1)

这种情况正在发生,因为您放入estimates DictProxy的对象实际上与生活在常规字典中的对象不同。 manager.dict()调用返回DictProxy,它代理访问实际位于完全独立的管理器进程中的dict。当您将内容插入其中时,它们将被复制并发送到远程进程,这意味着它们将具有不同的身份。

要解决此问题,您可以在__eq__上定义自己的__hash__A函数,described in this question

class A(object):
    def __init__(self,val):
        self.val = val

    # representative getValue function
    def getValue(self, est):
        return est[self] + self.val

    def __hash__(self):
        return hash(self.__key())

    def __key(self):
        return (self.val,)

    def __eq__(x, y):
        return x.__key() == y.__key()

这意味着estimates中项目的关键查找只会使用val属性的值来建立标识和相等性,而不是Python指定的id。 / p>