2012-01-03 7 views
5

Un patrón no es infrecuente en los problemas del Proyecto Euler parece ser algo equivalente a:Emulando a Scala ParStream

Stream.from(1).map(f).takeWhile((_>0)).foldLeft(0L)(_+_) 

donde f es una función caro-a-cálculo que devuelve valores positivos hasta cierto punto desconocido, y devuelve ceros después de eso.

Me gusta la paralelización de cosas, especialmente cuando las colecciones paralelas de Scala y .par lo hacen tan fácil. Sin embargo, en ausencia de un ParStream, el mejor que he ocurre es:

val BATCH=1024 
Stream.from(1,BATCH).flatMap(
    i=>(i until i+BATCH).par.map(f) 
).takeWhile((_>0)).foldLeft(0L)(_+_) 

que no parece muy elegante y es sensible a la elección de BATCH valor (pero puede producir mejoras en la velocidad x4 en mi cuatro nucleos).

¿Alguna sugerencia para formas más limpias de lograr el mismo resultado?

+1

Los ejemplos que das no son equivalentes: por ejemplo, con 'val f = 15 - (_: Int)' y 'BATCH = 10' el primero da 105 y el segundo 95 –

+0

@Luigi: Es por eso que lo califiqué con "devuelve valores positivos hasta ... y devuelve ceros después de eso". Por ejemplo, funciona con def f (x) = 0 max (15-x). – timday

Respuesta

5

Bueno, puede que sea un poco más elegante con algo como Stream from 1 grouped BATCH map (_.par), aunque yo prefiero usar Iterator en este caso - de peso mucho más ligero que Stream, y no va a llenar la memoria de REPL como experimento con eso.

+0

Gracias; ¡Ni siquiera había notado el método agrupado antes! – timday