Python的random.sample和堆栈溢出

时间:2017-09-19 19:32:06

标签: python random multiprocessing

我一直在研究一个大型的Python科学项目,我遇到了堆栈溢出问题,基本上涉及random.sample()multiprocessing。我有一个Goo对象,其中包含大量Foo人,他们寻求交朋友。为此,他们使用p随机选择属于Foo的{​​{1}}其他Goo random.sample()。一旦完成,程序就会停止。

就是这样:

foo.py

class Foo(object):
    def __init__(self):
        self.friends = []

goo.py:

from foo import Foo
import random

class Goo(object):
    def __init__(self, nfoo):
        self.foo_list = [Foo() for i in range(nfoo)]

    def sim_goo(self):
        for f in self.foo_list:
            candidates = random.sample(self.foo_list, 5)
            f.friends = candidates

和main.py:

from goo import Goo

def do_sim(argument):
    g = Goo(argument)
    g.sim_goo()
    return g

并使用Jupyter我运行:

from main import do_sim
from multiprocessing import Pool
pool = Pool(processes = 2)
para_list = [1000, 1000]
result = pool.map_async(sim_goo, para_list).get()

引发MaybeEncodingError: Error sending result: '[<goo.Goo object at 0x0000003B15E60A90>]'. Reason: 'RecursionError('maximum recursion depth exceeded while pickling an object',)'

当它与para_list = [10, 10]一起使用时,我只能想象错误被引发,因为random.sample()变得太大而无法处理它所选择的列表太大,这在使用多处理时会出现问题。但1000 Foos并不多。

有人知道另一种选择吗?

谢谢你的时间!

最佳,

1 个答案:

答案 0 :(得分:2)

为了让您的Goo对象被腌制(将其传输到另一个进程),必须先对其所有Foo进行腌制。为了挑选每个Foo,他们的所有朋友Foo必须先被腌制。并腌制那些 Foo ......等等。很可能会有一连串的友谊链贯穿所有1000 Foo s(因此在酸洗过程中需要堆栈深度超过1000) - 但是默认的递归限制(在我的Python副本上) ,至少)只有1000。

如果您可以使用1000 Foo作为限制,则可能会略微提高递归限制 - sys.setrecursionlimit(1050)。如果您需要更多,则需要采用不同的方法。我想到的第一件事就是将每个Foo的友谊作为索引列表存储到Goo的{​​{1}}中,而不是实际引用其他foo_list }第