Scala аналоги QtConcurrent

Каковы аналоги QtConcurrent для Scala (или Java)? Т.е. упрощенная реализация MapReduce, параллельного отображения и foldl. Спасибо вам

Ответ 1

Вы можете использовать Scala Parallel Collections. В настоящее время они входят в состав ночных выпусков Scala и будут выпущены в Scala 2.9. Идея состоит в том, что большинство операций, доступных в обычных коллекциях, распараллеливаются, так что параллельные коллекции могут использоваться одинаково.

В настоящее время доступно несколько типов коллекций - параллельные диапазоны, параллельные массивы и параллельные попытки хеширования. Например, вы можете вызывать параллельные операции map и fold для параллельного массива следующим образом:

scala> val pa = (0 until 10000).toArray.par
pa: scala.collection.parallel.mutable.ParArray[Int] = ParArray(0, 1, 2, 3, 4, 5, 6,...

scala> pa.map(_ + 1)
res0: scala.collection.parallel.mutable.ParArray[Int] = ParArray(1, 2, 3, 4, 5, 6, 7,...

scala> pa map { v => if (v % 2 == 0) v else -v }
res1: scala.collection.parallel.mutable.ParArray[Int] = ParArray(0, -1, 2, -3, 4, -5,...

scala> pa.fold(0) { _ + _ }
res2: Int = 49995000

Существуют и другие операции параллельной сборки. Обратите внимание, что fold должен принимать ассоциативный оператор - в приведенном выше примере добавление ассоциативно ((A + B) + C == A + (B + C)), т.е. вы можете добавлять подпоследовательности чисел в любом порядке, и вы всегда будет получать ту же сумму (reduce имеет аналогичный контракт).

Еще одна вещь, о которой нужно помнить, заключается в том, что замыкания, передаваемые параллельным коллекциям, вызываются одновременно. Если у них есть побочные эффекты, такие как изменение локальной переменной в среде, эти обращения должны быть синхронизированы. Например, вы можете сделать что-то вроде этого:

scala> var a = 0                                                                                                                                                                 
a: Int = 0                                                                                                                                                                       

scala> pa foreach { a += _ }                                                                                                                                                     

scala> a                                                                                                                                                                         
res1: Int = 49995000             

scala> a = 0
a: Int = 0

scala> pa foreach { a += _ }

scala> a
res7: Int = 49990086

и имеют разные результаты каждый раз, потому что foreach вызывает { a += _ } параллельно. В приведенном выше примере a следует сделать синхронизированным, защищенным блокировкой или атомом.

Но идея состоит в том, чтобы использовать встроенные комбинаторы для выполнения задачи и ориентироваться на функциональное программирование, избегая локальных побочных эффектов, как в приведенном выше примере.

Возможно, вы захотите прочитать немного больше об их внутренних механизмах в ссылках, представленных в другом ответе.

Ответ 3

Вы можете пройти долгий путь, используя scala.actors.Futures и обычный map/flatMap по коллекциям. Однако нет возможности легко распараллеливать fold.

Если вы перейдете на несколько хостов, я бы использовал для отправки и получения Akka.