当我想要在同一输入上调用几个昂贵的操作然后收集结果时,我可以使用Scala的并行集合吗?

时间:2011-10-23 21:01:21

标签: scala parallel-collections

我找到了一个similar question,但它有一个似乎更简单的情况,昂贵的操作始终是相同的。就我而言,我想收集一些我希望并行执行的昂贵API调用的结果。

说我有:

def apiRequest1(q: Query): Option[Result]
def apiRequest2(q: Query): Option[Result]

其中q是相同的值。

我想要一个List[Result]或类似的(显然List[Option[Result]]很好),我希望两个昂贵的操作并行发生。

当然,简单的List构造函数不会并行执行:

List(apiRequest1(q), apiRequest2(q))

并行收藏可以帮助吗?或者我应该期待未来等?我可以想到使用并行集合的唯一方法似乎很简单:

 List(q, q).par.zipWithIndex.flatMap((q) =>
   if (q._2 % 2 == 0) apiRequest1(q._1) else apiRequest2(q._1)
 )

实际上,在所有条件相同的情况下,也许这并不是那么糟糕......

3 个答案:

答案 0 :(得分:14)

你为什么不写

List(apiRequest1 _, apiRequest2 _).par.map(_(q))

答案 1 :(得分:2)

快速而肮脏的解决方案:

scala> def apiRequest1(q: Query): Option[Result] = { Thread.sleep(1000); Some(new Result) }
apiRequest1: (q: Query)Option[Result]

scala> def apiRequest2(q: Query): Option[Result] = { Thread.sleep(3000); Some(new Result) }
apiRequest2: (q: Query)Option[Result]

scala> val f = List(() => apiRequest1(q), () => apiRequest2(q)).par.map(_())
f: scala.collection.parallel.immutable.ParSeq[Option[Result]] = ParVector(Some(Result@1f24908), Some(Result@198c0b5))

答案 2 :(得分:0)

如果你只有两个或少量的调用,并不存在并行化的阈值,我不确定它是否会实际并行工作,它可能会按照这么小的集合顺序工作,理由是它是不值得并行开销(它不能知道,因为它取决于你想要运行的操作,但是在收集操作上有一个阈值是合理的。)