6

我一直在花一些时间试图理解多处理,尽管它的细节让我未经训练的头脑无法理解。我已经能够得到一个池来返回一个简单的整数,但是如果该函数不只是像我能找到的所有示例那样返回一个结果(即使在文档中,这是一些我不太明白的晦涩示例.

这是我试图开始工作的一个例子。但是,我无法让它按预期工作,而且我确信有一个简单的原因。我可能需要使用队列或共享内存或管理器,但在阅读文档时,我似乎无法理解它的实际含义和作用。到目前为止,我所能理解的只是池功能。

另外,我正在使用一个类,因为我需要避免在这个问题的答案中使用全局变量。

import random

class thisClass:
    def __init__(self):
        self.i = 0

def countSixes(myClassObject):
    newNum = random.randrange(0,10)
    #print(newNum) #this proves the function is being run if enabled
    if newNum == 6:
        myClassObject.i += 1

if __name__ == '__main__':
    import multiprocessing
    pool = multiprocessing.Pool(1) #use one core for now

    counter = thisClass()

    myList = []
    [myList.append(x) for x in range(1000)]

    #it must be (args,) instead of just i, apparently
    async_results = [pool.apply_async(countSixes, (counter,)) for i in myList]

    for x in async_results:
        x.get(timeout=1)

    print(counter.i)

有人可以愚蠢地解释需要做什么,这样我才能最终了解我缺少什么以及它做了什么?

4

1 回答 1

12

我花了一段时间才明白你想要发生什么。问题与多处理的工作方式有关。基本上,您需要以函数式风格编写程序,而不是像现在这样依赖副作用。

现在,您正在将对象发送到您的池中以进行修改,并且从countSixes. 这不适用于 multiprocessing ,因为为了回避GIL, multiprocessing 会创建一个副本并将其counter发送给一个全新的解释器。因此,当您增加 时i,实际上是在增加 的副本i然后,因为您什么也不返回,所以您将其丢弃!

要做一些有用的事情,你必须从countSixes. 这是您的代码的简化版本,它执行与您想要的类似的操作。我留下了一个参数,只是为了说明你应该做什么,但实际上这可以通过一个零参数函数来完成。

import random

def countSixes(start):
    newNum = random.randrange(0,10)
    if newNum == 6:
        return start + 1
    else:
        return start

if __name__ == '__main__':
    import multiprocessing
    pool = multiprocessing.Pool(1) #use one core for now

    start = 0
    async_results = [pool.apply_async(countSixes, (start,)) for i in range(1000)]

    print(sum(r.get() for r in async_results))
于 2011-06-15T16:22:06.030 回答