Python池生成池

时间:2017-09-21 16:09:03

标签: python multithreading multiprocessing

我有一个使用multiprocessing.Pool并行处理一个数据集中的所有数据的函数。

from multiprocessing import Pool
...
def func():
    ...
    p = Pool(processes=N)
    p.map(func, params)
    ...

但是,我现在想要并行运行M个不同的数据集。所以我在上面的现有脚本之上编写了另一个脚本。我再次尝试使用Pool创建M个进程(每个进程都会产生Pool个进程N。但是,我得到一个关于守护进程无法生成孩子的错误(这听起来非常摇滚)。所以我做了一些阅读,并为知道Pool切换multiprocessing.pool.ThreadPool。所以它看起来像

p = ThreadPool(processes=M)
p.starmap(func, args)

但是,当我运行它时,我发现ThreadPool一次只处理一个数据集。那么我应该使用什么来生成一个产生M个孩子的脚本,每个孩子都会产生N个孩子并且并行完成。

2 个答案:

答案 0 :(得分:1)

只需写出外部池并使用Process代替。由于GIL,线程在Python中的表现非常糟糕。

除了提出这个想法之外,这并没有做任何事情:

from multiprocessing import Pool, Process
from time import sleep
from random import randint

list = [1,2,3,4,5,6,7]

def worker(a):
    print a
    sleep(randint(0,2))


def f1(a):
    _p = Pool(processes=7)
    _p.map(worker, list)
    _p.close()
    _p.join()


def f2():
    processes = []
    for _i in list:
        p = Process(target=f1, args=(_i,))
        p.start()
        processes.append(p)
    for _q in processes:
        q.join()

f2()

它将启动七个进程,每个进程再启动一个池,f2等待所有进程完成。

答案 1 :(得分:1)

以下是Manager.Queue()的示例。 (不是我在评论中写的监视器,我的不好)。这是一个非常简单的程序,如果你拿出所有的键盘中断异常处理试图让它很好地关闭,它仍然没有做到。现在,您拥有一个外部进程池,进而生成一个池来执行任务。队列用于将任务提供给外部池工作者,后者又将它们提供给工作者。它们处于无限循环中,等待某些东西进入队列。

您当然可以在那里添加控制消息(例如,如果外部池工作人员收到单词"退出",它将关闭其池并很好地退出)如果您想管理外部池工人并告诉他们做不同的事情。

from multiprocessing import Pool, Process
from time import sleep
from random import randint
from multiprocessing import Manager
import sys


alist = [1, 2, 3, 4, 5, 6, 7]


def worker(a):
    try:
        print a
        sleep(randint(0, 2))
    except KeyboardInterrupt:
        pass


def outer_pool(iq, n):
    _ip = Pool(processes=7)
    try:
        while True:
            y = iq.get()
            _param = []
            for _ny in alist:
                _param.append("%d - %d - %d" % (n, _ny, y))
            _ip.map(worker, _param)

    except KeyboardInterrupt:
        try:
            _ip.terminate()
        except:
            pass


c_queue = Manager().Queue()

o_processes = []
for t in alist:
    p = Process(target=outer_pool, args=(c_queue, t))
    p.start()
    o_processes.append(p)

try:
    while True:
        a = randint(42,100)
        c_queue.put(a)
except KeyboardInterrupt:

    for _p in o_processes:
        try:
            _p.terminate()
        except:
            pass
    sys.exit(0)