我的代码草图如下:
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)
正如您可能从代码中了解到的那样,问题是,每当条件为真时,即在b
被a
替换之前,我希望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)