我花了一些时间试图理解多处理,虽然它的细节避开了我未经训练的头脑。我已经能够得到一个池来返回一个简单的整数,但是如果该函数不仅仅返回一个结果,就像我能找到的所有例子一样(即使在documentation中,这是一个不起眼的例子,我可以不太明白。
这是我试图开始工作的一个例子。但是,我不能按预期工作,我确信这有一个简单的原因。我可能需要使用队列或共享内存或管理器,但是当我阅读文档时,我似乎无法将我的大脑包围在它实际意味着什么以及它做什么。迄今为止我能够理解游泳池功能。
另外,我正在使用一个类,因为我需要避免在this question's answer中使用全局变量。
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)
有人可以愚蠢地解释需要做什么,这样我才能最终理解我所缺少的东西以及它的作用?
答案 0 :(得分:12)
我花了一段时间才明白你想要发生什么。问题与多处理的工作方式有关。基本上,您需要以功能样式编写程序,而不是像现在一样依赖副作用。
现在,您正在向池中发送要修改的对象,并且不会从countSixes
返回任何内容。这不适用于多处理,因为为了回避GIL,多处理会创建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))