实用的设计模式来执行阻止等待子任务结果的任务?

时间:2019-02-28 01:12:36

标签: python distributed-computing

我试图看看是否有可能采用通用(串行)算法,并通过简单地对关键函数进行注释,使它们以并行和分布式方式执行。目标:

  1. 无需对算法进行重大的结构重组以适应并行性,并且
  2. 通过将注释设为无操作,我应该能够使我的算法连续运行(=可调试)。
  3. 我希望compute-resource不必太在意正在执行的任务的细节。

这对于简单的任务来说是微不足道的,但对于我们也要分发的具有相关计算的任务而言,却并不明显。假设我有任务:

@distributed(pool)
def task1()
   # Task1 has dependent, distributed computation
   # Cannot return until a and b are both computed by subtasks
   a = task2(11)
   b = task2(22)

   # Continue and do more processing, which may be
   # complex and time consuming:
   result = a + b

   return result


@distributed(pool)
def task2(x): .... return x*10

@distributed注释负责对包装的任务函数及其参数的调用的序列化,并返回结果。

上面的问题是:

   a = task2(11)
   b = task2(22)

会顺序提交到池中,并且不会从并行性中受益。因此,假设我们以两种方式之一对其进行修复:

  • @distributed返回一个future,并且直到计算结果的值时才阻塞。 (我们必须致电a.await()+b.await())或

  • 我们明确引用了该池:

     a,b = pool.map(task2, [(11,), (22,)])
    

    and pool.map知道,当看到@distributed时,它应该“做正确的事”并分发包装的函数。

好的,要求(1)有点软,但到目前为止,已经足够简单了。

此模式的困难在于,如果pool仅具有2个可用工人,而我提交了2x task1,则当task2提交给池时,我们可能出现死锁task2无法执行,因为两个工作人员都在忙于执行task1并等待其结果。

什么是解决此问题的好模式,这样我可以有一个(分布式)工作池来执行我的所有作业,而对代码的入侵最少。


常见解决方案:

  • 每个工作人员一个主题(/任务类型):每种工作类型都有一组工作人员可以避免在上述情况下出现死锁,但是在递归任务(例如决策树构建)的一般情况下,则不会。这也很麻烦,因为我们必须定义哪些工人负责哪些任务(失败3)。基于Akka和AMPQ的系统似乎可以这种方式工作。

  • Theadpools可以解决死锁问题:

    • 如果池中没有空闲工人,请不要将作业提交到池中,然后立即执行作业而不将其提交到池中。效果很好,但由于在提交到队列还是在本地执行需要全局事务,因此尚不清楚如何在分布式环境中进行此工作。

我觉得我在这里缺少一个好的模式,这将帮助我避免重构很多可分发的代码。

0 个答案:

没有答案