使用共享队列和结束条件进行多处理

时间:2018-02-22 12:32:50

标签: python multiprocessing

我有这个原始功能,我想切换到多进程:

def optimal(t0, tf, frequences, delay, ratio = 0):

    First = True                            # First        
    for s in delay:
        delay = 0                           # delay between signals,
        timelines = list()

        for i in range(len(frequences)):
            timelines.append(time_builder(frequences[i], t0+delay, tf))
            delay += s

       trio_overlap = trio_combination(timelines, ratio)

        valid = True
        for items in trio_overlap.values():
            if len(list(set(items))) == len(items):
                continue
            else:
                valid = False

        if not valid:
            continue

        overlap = duo_combination(timelines)

    optimal = ... depending of conditions        
    return optimal

如果在测试后valid = True,它将计算一个名为optim_param的优化参数,并尝试将其最小化。如果它低于某个阈值optim_param < 0.3,我会跳出循环并将此值作为我的答案。

我的问题是,当我开发模型时,复杂性开始上升,单线程计算耗时太长。我想并行处理计算。由于每个进程都必须将使用s值获得的结果与当前最优值进行比较,因此我尝试实现了一个队列。

这是我第一次进行多处理,即使我认为我走在正确的轨道上,我也觉得我的代码很乱,不完整。我可以得到一些帮助吗?

谢谢:D

1 个答案:

答案 0 :(得分:4)

不要为每种情况手动创建流程,而应考虑使用Pool.imap_unordered。诀窍是如何在获得可通过的结果时干净地关闭:你可以通过传递一个早期退出的生成器来实现这一点,如果设置了一个标志,它会检查每个周期。主程序从迭代器读取,保持最佳结果,并在足够好时设置标志。最后一个技巧是减慢来自生成器的(内部)线程读取速度,以防止在获得良好结果后必须等待(或者,不清楚,被杀死)的大量计划任务积压。考虑到池中的进程数,可以使用信号量实现该调步。

以下是一个示例(通过简单分析)来演示:

import multiprocessing,threading,os

def interrupted(data,sem,interrupt):
  for x in data:
    yield x
    sem.acquire()
    if interrupt: break

def analyze(x): return x**2

np=os.cpu_count()
pool=multiprocessing.Pool(np)
sem=threading.Semaphore(np-1)
token=[]                        # mutable

vals=pool.imap_unordered(analyze,interrupted(range(-10,10),sem,token))
pool.close()                    # optional: to let processes exit faster

best=None
for res in vals:
  if best is None or res<best:
    best=res
    if best<5: token.append(None) # make it truthy
  sem.release()
pool.join()

print(best)

当然还有其他方法可以与发生器共享信号量和中断标志;这种方式使用丑陋的数据类型,但具有不使用全局变量(甚至闭包)的优点。