我有一个使用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
个孩子并且并行完成。
答案 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)