2016-11-15 1 views
0

Je comprends que /: est identique à foldLeft et aussi que aggregate est une version plus rapide de foldLeft si la liste est convertie en collection parallèle en utilisant 'par'. Si j'ai raison, pourquoi le code suivant montre-t-il que:/et foldLeft sont plus rapides que l'agrégat utilisé avec 'par' dans la liste.Scala - comparaison des performances de l'agrégat vs foldLeft

Je calcule la somme des éléments et du nombre d'éléments d'une grande liste et stocke le résultat dans un tuple [Double, Double].

//initial tuple2 (sum,count) 

val tsc:Tuple2[Double,Double] = Tuple2(0.0,0.0) 

//create a large list 
val largeList = List.tabulate(500000)(n=>n*n) 

//note time 
val time1 = System.currentTimeMillis 

//using aggregate without par 
largeList.aggregate(tsc) ((tsc,elem) => (tsc._1+elem, tsc._2+1), (tsc1, tsc2)=>((tsc1._1+tsc2._1), (tsc1._2+tsc2._2))) 

//note time 
val time2 = System.currentTimeMillis 

//use aggregate with par 

largeList.par.aggregate(tsc) ((tsc,elem) => (tsc._1+elem, tsc._2+1), (tsc1, tsc2)=>((tsc1._1+tsc2._1), (tsc1._2+tsc2._2))) 

//note time 
val time3 = System.currentTimeMillis 

//use /: 
(tsc /: largeList)((tsc,elem)=>(tsc._1+elem, tsc._2+1)) 

//note time 
val time4 = System.currentTimeMillis 

//use foldLeft 
largeList.foldLeft(tsc)((tsc,elem)=>(tsc._1+elem, tsc._2+1)) 

//note time 
val time5 = System.currentTimeMillis 

//calcualte time difference 
println ("Time without par (millisecond)"+(time2-time1)) 

println ("Time with par (millisecond)"+(time3-time2)) 

println ("Time with /: (millisecond)"+(time4-time3)) 

println ("Time with FoldLeft (millisecond)"+(time5-time4) 

J'ai obtenu le résultat suivant

résultat le 1er résultat run

Time without par (millisecond)1198 
Time with par (millisecond)1479 
Time with /: (millisecond)626 
Time with FoldLeft (millisecond)661 

sur 2ème manche

Time without par (millisecond)703 
Time with par (millisecond)581 
Time with /: (millisecond)435 
Time with FoldLeft (millisecond)423 

Je suis en cours d'exécution dans Windows 10 en utilisant cmd. /: et FoldLeft semblent similaires en performance et sont considérablement meilleurs que l'agrégat. Agréger avec par était en fait plus de temps en première manche. Pourrait-il être un problème dû à 'cmd' (console) dans la fenêtre ne pouvant pas tirer parti de multi-threading (juste deviner ici)

Répondre

1

Plusieurs problèmes. Votre ensemble de données est vraiment très petit (donc la surcharge de la parallélisation et de la gestion des threads est importante). L'utilisation de List signifie que l'étape de fusion de votre agrégat est O (N) - cela semble être le facteur le plus significatif une fois que vous augmentez la taille de l'ensemble de données.

Passage à Vector et en utilisant un vecteur 10 fois plus grande, je reçois:

Time without par (millisecond)271 
Time with par (millisecond)297 
Time with /: (millisecond)216 
Time with FoldLeft (millisecond)274 

qui est moins dramatique. Je ne faisais qu'un seul passage, dans une feuille de calcul Scala, donc je voyais beaucoup de variabilité dans ces chiffres

(J'ai seulement un système à deux cœurs donc le temps de parallélisation est significatif par rapport aux gains, il me semble)