执行没有多处理池映射的进程列表

时间:2014-12-17 13:37:22

标签: python multithreading multiprocessing

import multiprocessing as mp

if __name__ == '__main__':

    #pool = mp.Pool(M)

    p1 = mp.Process(target= target1, args= (arg1,))
    p2 = mp.Process(target= target2, args= (arg1,))
    ...
    p9 = mp.Process(target= target9, args= (arg9,))
    p10 = mp.Process(target= target10, args= (arg10,))
    ...
    pN = mp.Process(target= targetN, args= (argN,))

    processList = [p1, p2, .... , p9, p10, ... ,pN]

我有N个不同的目标函数,它们消耗不等的非平凡时间来执行。

我正在寻找一种并行执行它们的方法,以便M(1< M< N>)进程同时运行。一旦流程完成,下一个流程应该从列表开始,直到processList中的所有流程都完成。

由于我没有调用相同的目标函数,因此我无法使用Pool

我考虑做过这样的事情:

    for i in range(0, N, M):
        limit = i + M
        if(limit > N):
            limit = N
        for p in processList[i:limit]:
            p.join()

由于我的目标函数消耗的执行时间不等,因此该方法效率不高。

有什么建议吗?提前谢谢。

编辑: 问题标题已从“执行没有多处理池的进程列表”更改为“执行没有多处理池映射的进程列表”。

5 个答案:

答案 0 :(得分:4)

您可以使用proccess Pool

#!/usr/bin/env python
# coding=utf-8

from multiprocessing import Pool
import random
import time


def target_1():
    time.sleep(random.uniform(0.5, 2))
    print('done target 1')

def target_2():
    time.sleep(random.uniform(0.5, 2))
    print('done target 1')

def target_3():
    time.sleep(random.uniform(0.5, 2))
    print('done target 1')

def target_4():
    time.sleep(random.uniform(0.5, 2))
    print('done target 1')


pool = Pool(2) # maximum two processes at time.
pool.apply_async(target_1)
pool.apply_async(target_2)
pool.apply_async(target_3)
pool.apply_async(target_4)
pool.close()
pool.join()

专门为您需要做的事情创建池 - 在有限数量的进程中执行许多任务。

我还建议您查看concurrent.futures库,backport to Python 2.7。它有一个ProcessPoolExecutor,它具有大致相同的功能,但它的方法返回Future个对象,并且它们有一个更好的API。

答案 1 :(得分:3)

这是一种在Python 3.4中实现的方法,可以适用于Python 2.7:

targets_with_args = [
    (target1, arg1),
    (target2, arg2),
    (target3, arg3),
    ...
]

with concurrent.futures.ProcessPoolExecutor(max_workers=20) as executor:
    futures = [executor.submit(target, arg) for target, arg in targets_with_args]
    results = [future.result() for future in concurrent.futures.as_completed(futures)]

答案 2 :(得分:1)

我会使用Queue。从processList向它添加进程,一旦进程完成,我会将其从队列中删除并添加另一个。

伪代码看起来像:

from Queue import Queue
q = Queue(m)

# add first process to queue
i = 0
q.put(processList[i])
processList[i].start()
i+=1

while not q.empty():
    p=q.get()

    # check if process is finish. if not return it to the queue for later checking
    if p.is_alive():
        p.put(t)

    # add another process if there is space and there are more processes to add
    if not q.full() and i < len(processList):
        q.put(processList[i])
        processList[i].start()
        i+=1

答案 3 :(得分:0)

一个简单的解决方案是将函数target {1,2,... N}包装到单个函数forward_to_target中,该函数根据参数转发到适当的目标{1,2,... N}函数。传入。如果无法从当前使用的参数中推断出相应的目标函数,请用元组(argX,X)替换每个参数,然后在forward_to_target函数中解压缩元组并转发到X指示的相应函数。

答案 4 :(得分:0)

你可以有两个list个目标和参数,zip两个一起 - 并将它们发送给一个跑步者功能(这里是run_target_on_args):

#!/usr/bin/env python

import multiprocessing as mp

# target functions
targets = [len, str, len, zip]

# arguments for each function
args = [["arg1"], ["arg2"], ["arg3"], [["arg5"], ["arg6"]]]

# applies target function on it's arguments
def run_target_on_args(target_args):
    return target_args[0](*target_args[1])

pool = mp.Pool()
print pool.map(run_target_on_args, zip(targets, args))