繁体   English   中英

使用期货并行化scala中的递归分支计算

[英]Parallelizing recursive branching computations in scala using futures

我正在尝试使用Future在Scala中并行化SAT求解器。

解决SAT问题的算法大致类似于(伪代码):

def has_solution(x):
    if x is a solution:
        return true
    else if x is not a solution:
        return false
    else:
        x1 = left_branch(x)
        x2 = right_branch(x)
        return has_solution(x1) or has_solution(x2)

因此,每当我分支问题时,我就有机会并行化计算。

我该如何使用期货? 我需要等待has_solution(x1)和has_solution(x2)的结果,并且:

  1. 只要任一分支返回true,就返回true
  2. 如果两个分支都返回false,则返回false

我当前的方法如下:

object DPLL {
  def apply(formula: Formula): Future[Boolean] = {
    var tmp = formula

    if (tmp.isEmpty) {
      Future { true }
    } else if (tmp.hasEmptyClause) {
      Future { false }
    } else {

      for (unitClause <- tmp.unitClauses) tmp = tmp.propagateUnit(unitClause);
      for (pureLiteral <- tmp.pureLiterals) tmp = tmp.assign(pureLiteral);

      if (tmp.isEmpty())
        Future { true }
      else if (tmp.hasEmptyClause)
        Future { false }
      else {
        val nextLiteral = tmp.chooseLiteral

这是发生分支的地方,我想等待如上所述的计算:

        for (f1 <- DPLL(tmp.assign(nextLiteral)); 
             f2 <- DPLL(tmp.assign(-nextLiteral)))
          yield (f1 || f2)
      }
    }
  }
}

当我运行它时,这看起来是错误的,因为我永远无法充分利用我的内核(8)。

我有一种直觉,我不应该将期货用于这种计算。 也许期货只适合异步计算。 我是否应该为此尝试一些较低级别的线程或基于参与者的方法? 谢谢。

此代码因for块而顺序工作! f1计算完成后, f2计算开始。

for {
  f1 <- DPLL(tmp.assign(nextLiteral))
  f2 <- DPLL(tmp.assign(-nextLiteral))
} yield f1 || f2

上面的代码块转换为以下flatMap/map序列, flatMap/map作用是在值存在后运行该函数。

DPLL(tmp.assign(nextLiteral)).flatMap(f1 =>
  DPLL(tmp.assign(-nextLiteral)).map(f2 =>
    f1 || f2)

并行开始计算的一个简单技巧是将它们分配给一个值并访问该值以进行理解

val comp1 = DPLL(tmp.assign(nextLiteral))
val comp2 = DPLL(tmp.assign(-nextLiteral))
for {
  f1 <- comp1
  f2 <- comp1
} yield f1 || f2

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM