2012-01-03 6 views
5

Un modello non raro in problemi di Project Euler sembra essere qualcosa di equivalente a:Emulare una scala ParStream

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

dove f è una funzione costosa-to-calcolo che restituisce valori positivi fino a un certo punto sconosciuto e restituisce zeri dopo.

Mi piace parallelizzare le cose, soprattutto quando le raccolte parallele di Scala e .par rendono tutto così semplice. Ma, in assenza di un ParStream, la migliore che è venuta in mente è:

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

che non sembra molto elegante ed è sensibile alla scelta di BATCH valore (ma può produrre miglioramenti di velocità x4 sul mio quad core).

Qualche suggerimento per modi più puliti per ottenere lo stesso risultato?

+1

Gli esempi forniti non sono equivalenti: ad esempio con 'val f = 15 - (_: Int)' e 'BATCH = 10' il primo dà 105 e il secondo 95 –

+0

@Luigi: Ecco perché l'ho qualificato con "restituisce valori positivi fino a ... e restituisce zeri dopo". per esempio funziona con def f (x) = 0 max (15-x). – timday

risposta

5

Beh, si può rendere un po 'più elegante con qualcosa di simile Stream from 1 grouped BATCH map (_.par), anche se io preferisco usare Iterator in questo caso - di peso molto più leggero di Stream, e non sarà riempire la memoria di REPL come sperimento esso.

+0

Grazie; Non avevo nemmeno notato il metodo raggruppato prima! – timday