并行处理-python中的递归函数调用和排队



我的代码草图如下:

def func1(c):
    return a,b
def func2(c,x):
    if condition:
        a,b = func1(c)
        x.append(a,b)
        func2(a,x)
        func2(b,x)
    return x
x = []
y = func2(c, x)

正如您可能从代码中了解到的那样,问题是,每当条件为真时,即在ba替换之前,我希望func2(b)func2(a)并行计算,即func2(a)中的新b。但根据我的算法,由于新的b,这显然不可能发生。

我确实认为,对于并行计算方法来说,这样的问题可能是完美的。但是,我以前没有使用过它,我对它的了解非常有限。不过,我确实尝试了《如何在Python中进行并行编程》中的建议。但我得到了与上面的草图相同的结果。

注意:线程对您来说可能不够并行(请参阅https://docs.python.org/2/library/threading.html注意Global Interpreter Lock),因此您可能不得不使用multiprocessing库(https://docs.python.org/2/library/multiprocessing.html)。

所以我作弊/懒惰了&使用了与线程/进程无关的术语"作业"。对于我使用"job"的任何地方,您都需要选择线程或多处理。

def func1(c):
    return a,b
def func2(c,x):
    if condition:
        a,b = func1(c)
        x.append(a,b)
        a_job = None
        if (number_active_jobs() >= NUM_CPUS):
            # do a and b sequentially
            func2(a, x)
        else:
            a_job = fork_job(func2, a, x)
        func2(b,x)
        if a_job is not None:
            join(a_job)
x = []
func2(c, x)
# all results are now in x (don't need y)

如果出于某种原因,你需要a、b组合在一起完成比赛,那将是最好的。如果你愿意让调度器发疯,你可以把它们全部"工作";则最后的join

def func1(c):
    return a,b
def func2(c,x):
    if condition:
        a,b = func1(c)
        x.append(a,b)
        if (number_active_jobs() >= NUM_CPUS):
            # do a and b sequentially
            func2(a, x)
        else:
            all_jobs.append(fork_job(func2, a, x))
        # TODO: the same job-or-sequential for func2(b,x)
all_jobs = []
x = []
func2(c, x)
for j in all_jobs:
    join(j)
# all results are now in x (don't need y)

NUM_CPUS检查可以用threading.activeCount()而不是一个完整的工作线程池来完成(python-如何获得特定类启动的活动线程的numebr?)。

但是,使用多处理,JoinableQueue和固定大小的工人的Pool将有更多的工作要做

根据您的解释,我有一种感觉,不是b得到了更新(正如DouglasDD所解释的那样,这不是),而是x。要让两个递归调用在同一个x上工作,需要对x进行某种快照。最简单的方法是沿着的行传递新附加的元组的索引

def func2(c, x, length):
    ...
    x.append(a, b)
    func2(a, x, length + 1)
    func2(b, x, length + 1)

最新更新