并行化递归python

时间:2014-09-21 01:57:08

标签: python python-3.x parallel-processing multiprocessing python-multiprocessing

我正在使用大数据集。我的输入将是4个不同的数据集,我必须将特定的函数应用于每个数据集。所以我所做的就是读取所有四个数据集并使用pool.map并行地将函数应用于每个数据集。所以现在我有一个父母和4个孩子的过程。在此之前一切都很好。

Q1。现在每个过程中发生了什么。在我应用于每个数据集的函数中,我将每个元组与其他元组进行比较,因此它是一种递归。有没有办法让它并行,因为这种比较可能需要很长时间,因为数据集会很大。如何制作它因为它已经是一个子进程?是否有可能在子进程中再次并行化,因为我有更多的处理器,所以我想利用它。

Q2。对于这个递归任务的并行化我想到的是,如果我将元组x与元组y(每个元组与所有其他元组)进行比较,我可以为x创建块,并且每个块与y进行比较。我猜这可以通过两个for循环来完成。有什么建议怎么做?

1 个答案:

答案 0 :(得分:4)

Re:Q1,如果您使用multiprocessing.Pool创建子进程,则不然,工作进程无法生成子进程。尝试创建一个将引发异常:

AssertionError: daemonic processes are not allowed to have children

原因很清楚 - Pool中的过程是守护进程,而守护进程无法生成孩子。这样做的原因是终止父进程将终止其守护进程的子进程,但守护进程的子进程将无法终止他们的子进程,这将留下孤立进程。这在documentation

中说明
  

请注意,不允许守护进程创建子进程。   否则,守护进程会使其子女成为孤儿   当父进程退出时终止。

您可以通过父进程来创建一组非守护进程Process对象,而不是使用Pool。然后,每个孩子都可以创建自己的multiprocessing.Pool

import multiprocessing

def subf(x):
    print "in subf"

def f(x):
    print "in f"
    p = multiprocessing.Pool(2)
    p.map(subf, range(2))


if __name__ == "__main__":
    processes = []
    for i in range(2):
        proc = multiprocessing.Process(target=f, args=(i,))
        proc.start()
        processes.append(proc)

输出:

in f
in f
in subf
in subf
in subf
in subf

这种方法似乎对您有效,因为您的初始数据集只包含四个项目。您只需在数据集中为每个项目创建一个Process,并且仍然可以为每个子流程提供一些空闲的CPU,以便在较小的Pool中使用。

Re:Q2,听起来你可以使用itertools.product创建一对想要比较的元组的大迭代。然后,您可以使用pool.map并行比较每对。以下是展示其运作方式的示例:

def f(x):
    print(x)

if __name__ == "__main__":
    # Create two lists of tuples, like your use-case
    x = zip(range(3), range(3,6))
    y = zip(range(6, 9), range(9, 12))

    pool = multiprocessing.Pool()
    pool.map(f, itertools.product(x, y))

输出:

((0, 3), (6, 9))
((0, 3), (7, 10))
((0, 3), (8, 11))
((1, 4), (6, 9))
((1, 4), (7, 10))
((1, 4), (8, 11))
((2, 5), (6, 9))
((2, 5), (8, 11))
((2, 5), (7, 10))