我有这个原始功能,我想切换到多进程:
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
答案 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)
当然还有其他方法可以与发生器共享信号量和中断标志;这种方式使用丑陋的数据类型,但具有不使用全局变量(甚至闭包)的优点。