2015-03-24 8 views
5

Ich war über die neuen Funktionen in Java lesen 8 und einer von ihnen war der neue Arrays.parallelSort() -Methode. Ich machte einige Tests, die eine Reihe von Doppel und eine von Strings sortierten und für Strings war die ParallelSort viel langsamer. HierParallel Art langsamer als Serien Art

ist der Inhalt eines Testverfahrens für Streicher:

final int size = 10000; 
    final String[] values1 = new String[size]; 
    final String[] values2 = new String[size]; 
    for (int i = 0; i < size; i++) { 
     values1[i] = Integer.toString(i); 
     values2[i] = values1[i]; 
    } 
    Collections.shuffle(Arrays.asList(values1)); 
    Collections.shuffle(Arrays.asList(values2)); 
    final Comparator<String> comparator = (o1, o2) -> o2.compareTo(o1); 

    long startTimeInNano = System.nanoTime(); 
    Arrays.sort(values1, comparator); 
    long endTimeInNano = System.nanoTime(); 
    System.out.println("Arrays.sort: totalTimeInMicro= " + ((endTimeInNano - startTimeInNano)/1000)); 

    //parallel sort with java 8 
    startTimeInNano = System.nanoTime(); 
    Arrays.parallelSort(values2,comparator); 
    endTimeInNano = System.nanoTime(); 
    System.out.println("Arrays.parallelSort: totalTimeInMicro= " + ((endTimeInNano - startTimeInNano)/1000)); 

Das Ergebnis war:

Arrays.sort: totalTimeInMicro= 11993

Arrays.parallelSort: totalTimeInMicro= 89823

Ich habe auch versucht, diesen Code auf einem anderen Computer und die Ergebnis war das gleiche (25608 vs 808660). Der Computer, auf dem ich die Tests durchführe, hat eine i5-2500 CPU. Hast du eine Idee, warum ich solche Ergebnisse bekomme?

+1

könnte darauf zurückzuführen sein, Schaffung Kopf einzufädeln. Versuchen Sie, noch größere Arrays zu sortieren: Es könnte möglich sein, dass es eine Array-Größe gibt, für die die parallele Sortierung schneller ist. – juhist

+3

Das Timing eines einzelnen Aufrufs (ohne sogar hochzufahren) wird dir nicht viel sagen. – biziclop

+0

1. Bevor Sie eine Mikrobankmarkierung durchführen, sollten Sie einen Aufwärmlauf durchführen. 2. 'Arrays.parallelSort()' 'verwendet gabel join' Rahmen. Es hängt also direkt mit der Anzahl der Kerne auf einem System zusammen (daher ist es * architekturabhängig *). i-5 hat 4 Kerne, also sollte idealerweise 'parallele Sortierung' schneller sein. – TheLostMind

Antwort

7

Dieser Benchmark zeigt Ihnen kaum etwas. Die wichtigsten Dinge für einen-Micro sind

  • Geben Sie den JIT eine Chance, um den Code zu optimieren, indem die Tests mehrfach ausgeführt
  • Verwenden Sie unterschiedliche Eingangsgrößen
  • drucken einige der Ergebnisse aus der JIT zu verhindern die ganze Optimierung entfernt ruft

Es gibt einige weitere Punkte zu berücksichtigen sind - in der Tat, viele mehr Punkte. Weitere Informationen erhalten Sie unter How do I write a correct micro-benchmark in Java?. Für wirklich "profunde" Informationen sollten Sie Tools wie Caliper oder JMH verwenden. Aber selbst mit wenig Aufwand kann man ein Mikrobenchmark erstellen, das einen ungefähren Hinweis darauf gibt, wie die tatsächliche Leistung aussehen würde. Damit wird eines der einfachsten Formen eines-Micro könnte wie folgt aussehen:

import java.util.Arrays; 
import java.util.Collections; 
import java.util.Comparator; 

public class ParallelSortSpeedTest 
{ 
    public static void main(String[] args) 
    { 
     for (int size=100000; size<=1000000; size+=100000) 
     { 
      final String[] values1 = new String[size]; 
      final String[] values2 = new String[size]; 
      for (int i = 0; i < size; i++) { 
       values1[i] = Integer.toString(i); 
       values2[i] = values1[i]; 
      } 
      Collections.shuffle(Arrays.asList(values1)); 
      Collections.shuffle(Arrays.asList(values2)); 
      final Comparator<String> comparator = (o1, o2) -> o2.compareTo(o1); 

      testSort(values1, comparator); 
      testParallelSort(values2, comparator); 
     } 
    } 

    private static void testSort(
     String array[], final Comparator<String> comparator) 
    { 
     long startTimeInNano = System.nanoTime(); 
     Arrays.sort(array, comparator); 
     long endTimeInNano = System.nanoTime(); 
     System.out.println("Arrays.sort  : totalTimeInMicro= " + 
      ((endTimeInNano - startTimeInNano)/1000)+", first "+array[0]); 
    } 

    private static void testParallelSort(
     String array[], final Comparator<String> comparator) 
    { 
     long startTimeInNano = System.nanoTime(); 
     Arrays.parallelSort(array, comparator); 
     long endTimeInNano = System.nanoTime(); 
     System.out.println("Arrays.parallelSort: totalTimeInMicro= " + 
      ((endTimeInNano - startTimeInNano)/1000)+", first "+array[0]); 
    } 

} 

Dies ist eine vernünftige Option, unter Berücksichtigung der Trade-off zwischen dem Aufwand einer JMH Benchmark bekommen und läuft, und die Zuverlässigkeit der die Ergebnisse. Dieser Test wird angezeigt etwas wie

... 
Arrays.sort  : totalTimeInMicro= 530669, first 999999 
Arrays.parallelSort: totalTimeInMicro= 158227, first 999999 

drucken, dass die parallele Sortierung sollte schneller sein, zumindest.

+0

Ich machte noch ein paar Tests mit einer Anfangsgröße von 50k und einer Vergrößerung um 50k auf 10 Millionen. Für die endgültige Größe, ich habe folgendes Ergebnis: 'Arrays.sort: totalTimeInMicro = 653.260 Arrays.parallelSort: totalTimeInMicro = 257168' – Slimu

+0

machte ich den Fehler, die einzelnen Durchläufe mit unterschiedlichen Werten gut genug für einen einfachen Test berücksichtigen. Ich werde mehr über Micro-Benchmarking lesen. – Slimu

+0

Echte Frage: Sollten Sie nicht nur einmal mischen, und dann das andere Array eine Kopie dieser Shuffle sein? Damit vergleichen Sie genau das Gleiche. Upvoted. – Peheje