2

假设我有一个名为 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()

所以问题是每次运行循环时每个狗对象都不会保留其跳蚤列表。我希望在每个循环结束时保留每只狗的跳蚤列表,所以在两个循环之后,每只狗都会有两个跳蚤,依此类推。有任何想法吗?我猜我得腌制一些东西。

4

3 回答 3

1

多处理文档建议尽可能不要共享状态,但您可能可以使用托管字典来实现您的目标:

http://docs.python.org/2/library/multiprocessing.html#sharing-state-between-processes

(请参阅基于服务器的管理器部分。)

这样,您可以根据您的核心逻辑更改单个托管对象,并且处理节点将看到更新的版本。你必须在你的代码中尝试一下,看看最好的共享设置是什么(如果有的话!)。

于 2013-05-06T00:20:56.000 回答
0

JF塞巴斯蒂安是正确的。您在循环中看不到突变的原因是它们发生在另一个过程中。看来你对流程不是很熟悉;你应该考虑更多地了解它们

您想从池中获取结果,并将它们复制到您当地的狗身上。一种方法是将循环修改为如下所示:

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))

有几点需要注意:

  1. 您应该避免在每次迭代期间创建新池。这避免了进程(池)创建的开销。
  2. some_number_of_processes可以< len(dogs)!每个过程都会产生一些开销;因此,存在收益递减点。通常高估一点比低估要好。但是,很容易避免严重高估,除非你真的很懒惰。

如果您使用的是 Python 3.2 或更高版本,并且dirty_dog 不受 CPU 限制(例如经常接触磁盘),那么请考虑改用ThreadPoolExecutor;这样,修改不需要被复制,因为线程将在相同的对象上操作,而不是副本。

于 2013-05-06T00:20:07.273 回答
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()
于 2013-05-06T00:49:42.080 回答