Могу ли я использовать параллельные коллекции Scala, когда у меня есть несколько дорогих операций, которые я хочу вызвать на одном входе, а затем собрать результаты? - PullRequest
3 голосов
/ 24 октября 2011

Я нашел похожий вопрос , но он имеет, как кажется, более простой случай, когда дорогостоящая операция всегда одинакова.В моем случае я хочу собрать набор результатов некоторых дорогих вызовов 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 ]

14 голосов
/ 24 октября 2011

Почему ты не пишешь

List(apiRequest1 _, apiRequest2 _).par.map(_(q))
2 голосов
/ 24 октября 2011

Быстрое и грязное решение:

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))
0 голосов
/ 24 октября 2011

Я не уверен, что на самом деле он будет работать параллельно, если у вас только два или небольшое количество вызовов, существует порог для распараллеливания, и он, вероятно, будет работать последовательно с таким небольшим набором на том основании, что не стоит затрат на распараллеливание (он не может знать, что это зависит от операции, которую вы хотите запустить, но разумно иметь порог для операций сбора).

...