Python 具有共享数据的多处理池
Python multiprocessing pool with shared data
我正在尝试使用多处理来加速多元定点迭代算法,但是,我在处理共享数据时遇到了 运行 问题。我的解决方案向量实际上是一个命名字典而不是数字向量。向量的每个元素实际上是使用不同的公式计算的。在高层次上,我有一个这样的算法:
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
"""
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
错误。并调试,发现none个元素是一样的
print map(id, estimates.keys())
>>> [19558864, 19558928, 19558992, 19559056, 19559120]
print map(id, all_states)
>>> [19416144, 19416208, 19416272, 19416336, 19416400]
发生这种情况是因为您放入 estimates
DictProxy
的对象实际上与常规字典中的对象不同。 manager.dict()
调用 returns a DictProxy
,这是对 dict
的代理访问,后者实际上存在于完全独立的管理器进程中。当您将东西插入其中时,它们实际上被复制并发送到远程进程,这意味着它们将具有不同的身份。
要解决此问题,您可以在 A
上定义自己的 __eq__
和 __hash__
函数,如 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
属性的值来建立身份和平等,而不是 id
分配的 Python.
我正在尝试使用多处理来加速多元定点迭代算法,但是,我在处理共享数据时遇到了 运行 问题。我的解决方案向量实际上是一个命名字典而不是数字向量。向量的每个元素实际上是使用不同的公式计算的。在高层次上,我有一个这样的算法:
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
"""
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
错误。并调试,发现none个元素是一样的
print map(id, estimates.keys())
>>> [19558864, 19558928, 19558992, 19559056, 19559120]
print map(id, all_states)
>>> [19416144, 19416208, 19416272, 19416336, 19416400]
发生这种情况是因为您放入 estimates
DictProxy
的对象实际上与常规字典中的对象不同。 manager.dict()
调用 returns a DictProxy
,这是对 dict
的代理访问,后者实际上存在于完全独立的管理器进程中。当您将东西插入其中时,它们实际上被复制并发送到远程进程,这意味着它们将具有不同的身份。
要解决此问题,您可以在 A
上定义自己的 __eq__
和 __hash__
函数,如 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
属性的值来建立身份和平等,而不是 id
分配的 Python.