2016-07-20 7 views
1

Ich habe das basic Beispiel aus dem Beispiel-Repository von ScalaMeter (https://github.com/scalameter/scalameter-examples) verwendet. Der Code des Beispiels ist wie folgt:Testen der Leistung von parallelen Aktionen mit ScalaMeter

measure method "map" in { 
    using(ranges) in { r => 
    r.map(_ + 1) 
    } 
} 

In meinem Fall möchte ich die Beschleunigung testen einige Aktionen parallel laufen. Ein einfaches Beispiel könnte sein, dass ich einen Bereich dividiere, der gemappt werden muss. Ich habe ExecutorService von Java8 verwendet, um die Aufgaben parallel auszuführen. Es sieht wie folgt aus:

val cores = Runtime.getRuntime.availableProcessors() 
val pool = Executors.newFixedThreadPool(cores) 

measure method "parallel map" in { 
    using(ranges) in { r => 
    val tasks = (0 until cores).map { t => 
     new Callable[Unit] { 
     override def call() = (0 + t until r.last by cores).map(_ + 1) 
     } 
    } 
    import collection.JavaConverters._ 
    pool.invokeAll(tasks.asJava) 
    } 
} 

Das Problem ist, dass, obwohl die parallelen Test beendet (Sie die Zeit, um Ergebnisse sehen) nicht den Exit-Code zurückgibt. Die Implikation ist, dass, wenn ich die Bench.LocalTime zu Bench.ForkedTime ändere sogar die Ergebnisse weg sind. Ich bin ziemlich verwirrt, was vor sich geht. Irgendwelche Ideen?

Antwort

1

OK, das war ziemlich trivial, weil ich shutdown() den Pool vergessen habe. Nach der Zugabe es nach invokeAll habe ich ein Ergebnis wie folgt:

measure method "parallel map" in { 
    using(ranges) in { r => 
    val pool = Executors.newFixedThreadPool(cores) 
    val tasks = (0 until cores).map { t => 
     new Callable[Unit] { 
     override def call() = (0 + t until r.last by cores).map(_ + 1) 
     } 
    } 
    pool.invokeAll(tasks.asJava) 
    pool.shutdown() 
    } 
} 

Das einzige Problem ist, dass jetzt nicht nur die Wirkung gemessen wird, sondern auch eine Zeit der Erstellung der ExecutorService und das Herunterfahren. Aber ich denke, es wird die Ergebnisse für die Zeit nicht ändern.


Eigentlich habe ich nach einiger Zeit einen einfacheren, mehr 'Scala' Weg gefunden, um das Obige zu tun. Sie können einfach eine Liste von Aufgaben als eine Liste von Funktionen erstellen (oder kann immer noch eine Liste von Callables sein) und später rufen Sie alle Aufgaben mit parallel Sammlungen. Code sieht wie folgt aus:

measure method "parallel map" in { 
    using(ranges) in { r => 
    val tasks = (0 until cores).flatMap { t => 
     (0 + t until r by cores).map(i =>() => i+1) 
    } 
    tasks.par.map(_.apply()) 
    } 
} 

oder noch einfacher, weil die Liste der Aufgaben, die nicht über die cores jetzt schert:

val tasks = (0 until r).map(i =>() => i+1) 
Verwandte Themen