[英]Parallelizing recursive branching computations in scala using futures
I am trying to parallelize a SAT solver in Scala using Futures. 我正在尝试使用Future在Scala中并行化SAT求解器。
The algorithm for solving a SAT problem is loosely like (pseudo-code): 解决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)
So I see an opportunity to parallelize the computation whenever I branch the problem. 因此,每当我分支问题时,我就有机会并行化计算。
How can I do this with Futures? 我该如何使用期货? I need to wait for results from has_solution(x1) and has_solution(x2), and:
我需要等待has_solution(x1)和has_solution(x2)的结果,并且:
My current approach is the following: 我当前的方法如下:
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
Here is where branching takes place and where I'd like to wait for the computations as described above: 这是发生分支的地方,我想等待如上所述的计算:
for (f1 <- DPLL(tmp.assign(nextLiteral));
f2 <- DPLL(tmp.assign(-nextLiteral)))
yield (f1 || f2)
}
}
}
}
This looks wrong when I run it because I can never achieve full use of my cores (8). 当我运行它时,这看起来是错误的,因为我永远无法充分利用我的内核(8)。
I have an intuition I should not be using futures for this kind of computation. 我有一种直觉,我不应该将期货用于这种计算。 Maybe futures are suited just for asynchronous computations.
也许期货只适合异步计算。 Should I try some lower-level threading or actor-based approach for this?
我是否应该为此尝试一些较低级别的线程或基于参与者的方法? Thanks.
谢谢。
This code works sequentially because of for block! 此代码因for块而顺序工作! Computation of
f2
starts after computation of f1
finished. f1
计算完成后, f2
计算开始。
for {
f1 <- DPLL(tmp.assign(nextLiteral))
f2 <- DPLL(tmp.assign(-nextLiteral))
} yield f1 || f2
Above block translates to following flatMap/map
sequence and what flatMap/map
does is to run the function after value is present. 上面的代码块转换为以下
flatMap/map
序列, flatMap/map
作用是在值存在后运行该函数。
DPLL(tmp.assign(nextLiteral)).flatMap(f1 =>
DPLL(tmp.assign(-nextLiteral)).map(f2 =>
f1 || f2)
One easy trick for starting computations in parallel is assigning them to a value and access that value in for comprehension 并行开始计算的一个简单技巧是将它们分配给一个值并访问该值以进行理解
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.