假设我有一些名为dog的课程:
class dog():
def __init__(self, name, age):
self.name = name
self.age = age
self.fleas = []
现在让我说我有一个名单,
names = ["bob", "joe", "dave"]
我创建了一个列表,执行以下操作:
dogs = [dog(name, index) for index, name in enumerate(names)] # Creates a list "dogs" that has 3 dog classes in it, named bob, joe, david, with ages 0, 1, 2 respectively.
现在我有一本跳蚤字典,
global_fleas = {"bob":[flea_43], "joe":[flea_20], "dave":[flea_3]}
并且有一些单独的方法flea_mod()
修改此词典,以便将每只狗的跳蚤号码更改为某个随机数,例如flea_50。在这本词典中,每只狗只会有一只跳蚤。
我可以通过执行以下操作将global_fleas中的跳蚤附加到相应的狗:
def dirty_dog(dog):
dog.fleas.append(global_fleas[dog.name])
这是踢球者。我想多处理这个循环。这就是我现在所拥有的:
while True:
flea_mod() # This randomizes the flea_number for each dog in the global_flea dictionary
pool = multiprocessing.Pool(processes=len(dogs))
[pool.apply_async(dirty_dog, dog) for dog in dogs]
pool.close()
pool.join()
所以问题是每次狗对象在每次循环运行时都不会保留其跳蚤列表。我希望每只狗的跳蚤清单在每个循环结束时保留,所以在两个循环后,每只狗将有两只跳蚤,依此类推。有任何想法吗?我猜我不得不腌制一些东西。
答案 0 :(得分:1)
多处理文档尽可能建议不要使用共享状态,但您可以使用托管字典来实现目标:
http://docs.python.org/2/library/multiprocessing.html#sharing-state-between-processes
(请参阅基于服务器的管理器部分。)
这样,您可以根据核心逻辑更改单个托管对象,处理节点将看到更新的版本。您必须在代码中尝试一下才能看到最佳的共享设置(如果有的话)。
答案 1 :(得分:0)
J.F塞巴斯蒂安是对的。你没有在循环中看到突变的原因是它们发生在另一个过程中。你似乎对流程不是很熟悉;你应该考虑learning more about them。
您想从泳池中取出结果,然后将它们复制到当地的狗身上。一种方法是修改你的循环,看起来像这样:
pool = multiprocessing.Pool(processes=some_number_of_processes)
while True:
flea_mod()
results = [pool.appy_async(dirty_dog, dog) for dog in dogs]
for result, dog in zip(results, dogs):
# I assume that dirty_dog returns the updated dog.
dog.update(result.get(timeout=some_positive_number_of_seconds))
有几点需要注意:
some_number_of_processes
可以是< len(dogs)
!每个过程都会产生一些开销因此,有一个收益递减点。通常情况下,高估一点而非低估则更好。但是,除非你真的很懒,否则很容易避免过高估计。如果您使用的是Python 3.2或更高版本,并且dirty_dog不受CPU限制(例如经常触摸磁盘),那么请考虑使用ThreadPoolExecutor;这样,不需要复制修改,因为线程将在相同的对象上操作,而不是复制。
答案 2 :(得分:0)
除非dirty_dog()
执行一些未在此处显示的冗长计算;多处理不会提高性能(通过来回复制数据可以获得所有好处)。
import multiprocessing as mp
def dirty_dog(i):
dog = dogs[i]
dog.fleas.append(global_fleas[dog.name])
dogs[i] = dog
def init(global_fleas_, dogs_):
global global_fleas, dogs
global_fleas, dogs = global_fleas_, dogs_
if __name__=="__main__":
manager = mp.Manager()
dogs = manager.list(dogs)
pool = mp.Pool(initializer=init, initargs=[global_fleas, dogs])
for _ in range(3):
flea_mod()
pool.map(dirty_dog, range(len(dogs)))
pool.close()
pool.join()