2010-09-18 8 views
10

¿Cuáles son los análogos de QtConcurrent para Scala (o Java)? Es decir, la implementación simplificada de MapReduce, el mapa paralelo y foldl. GraciasScala análogos de QtConcurrent

+0

ver también http://stackoverflow.com/questions/1751953/concurrent-map-foreach-in-scala/1753224#1753224 – oluies

Respuesta

3

Puede recorrer un largo camino usando scala.actors.Futures y map/flatMap normal en las colecciones. Sin embargo, no es fácilmente paralelizable fold.

Si usa varios hosts, usaría Akka's enviar y recibir-futuro.

12

Puede usar Colecciones paralelas de Scala. Actualmente son parte de los lanzamientos nocturnos de Scala y se lanzarán en Scala 2.9. La idea es que la mayoría de las operaciones disponibles en colecciones regulares estén paralelizadas, de modo que las colecciones paralelas se puedan usar de la misma manera.

Actualmente, hay algunos tipos de colecciones disponibles: rangos paralelos, matrices paralelas y hash paralelos. Por ejemplo, se puede invocar un paralelas map y fold operaciones en un conjunto paralelo de esta manera:

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 

Hay otras operaciones de recogida paralelos disponibles también. Tenga en cuenta que fold debe tomar un operador asociativo: en el ejemplo anterior, la adición es asociativa ((A + B) + C == A + (B + C)), es decir, puede agregar subsecuencias de números en cualquier orden y siempre lo hará obtener la misma suma (reduce tiene un contrato similar).

Otra cosa a tener en cuenta es que los cierres pasados ​​a colecciones paralelas se invocan simultáneamente. Si tienen efectos secundarios, como la modificación de una variable local en el entorno, estos accesos deben estar sincronizados. Por ejemplo, se podría hacer algo como esto:

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 

y tienen resultados diferentes cada vez, debido a que el foreach invoca { a += _ } en paralelo. En el ejemplo anterior, a se debe sincronizar, proteger con un candado o atómico.

Pero la idea es usar combinators incorporados para realizar una tarea e inclinarse hacia la programación funcional, evitando los efectos secundarios locales como en el ejemplo anterior.

Es posible que desee leer un poco más acerca de sus mecanismos internos en los enlaces proporcionados en la otra respuesta.

+0

Muy buena respuesta con un "empujón" lejos de las mutaciones ;-) –