Zu meiner Überraschung bekomme ich eine längere Zeit (10 Millisekunden), wenn ich Multiplikationen "optimiere", indem ich die Ergebnisse in einem Array im Vergleich zu den ursprünglichen 8 Millisekunden vorgeneriere. Ist das nur eine Java-Eigenart oder ist das die allgemeine PC-Architektur? Ich habe einen Core i5 760 mit Java 7, Windows 8 64 Bit.
%Vor%Konrad Rudolph kommentierte die Probleme mit dem Benchmarking . Also ignoriere ich den Benchmark und konzentriere mich auf die Frage:
Ist die Multiplikation schneller als der Array-Zugriff?
Ja, das ist sehr wahrscheinlich. Früher war es vor 20 oder 30 Jahren andersherum.
Grob gesagt, können Sie eine Integer-Multiplikation in 3 Zyklen durchführen (pessimistisch, wenn Sie keine Vektorinstruktionen erhalten), und ein Speicherzugriff kostet Sie 4 Zyklen, wenn Sie direkt aus der L1 Cache, aber von dort ist es direkt bergab. Als Referenz siehe
Latenzen und Durchsatz in Anhang C des Intel 64 und IA-32 Architectures Optimization Reference Manual
Ungefähre Kosten für den Zugriff auf verschiedene Caches und den Hauptspeicher?
Herb Sutters Präsentation zu diesem Thema: Maschinenarchitektur: Dinge, die Ihre Programmiersprache Ihnen nie gesagt hat a>
Eine Sache, die für Java spezifisch ist, war , auf die Ingo hingewiesen hat ein Kommentar unten: Sie erhalten auch Grenzen beim Einchecken von Java, was den ohnehin langsameren Array-Zugriff noch langsamer macht ...
Ein vernünftigerer Maßstab wäre:
%Vor%welches auf mein Intel Core Duo druckt (ja, es ist alt):
%Vor%Wenn ich also sequentiell auf das Lookup-Array zugreife, wodurch die Anzahl der Cache-Misses minimiert wird und die Hotspot-JVM die Grenzen beim Array-Zugriff optimieren kann, ergibt sich eine leichte Verbesserung gegenüber einem Array von 1000 Elementen. Wenn wir einen zufälligen Zugriff auf das Array ausführen, verschwindet dieser Vorteil. Wenn die Tabelle größer ist, wird die Suche langsamer. Zum Beispiel für 10000 Elemente bekomme ich:
%Vor%Also ist das Array-Lookup nicht schneller als die Multiplikation, es sei denn, das Zugriffsmuster ist (fast) sequentiell und das Lookup-Array ist klein.
In jedem Fall zeigen meine Messungen an, dass eine Multiplikation (und Addition) nur 4 Prozessorzyklen benötigt (2,3 ns pro Schleifeniteration auf einer 2 GHz CPU). Sie werden wahrscheinlich nicht viel schneller als das bekommen. Außerdem, wenn Sie nicht eine halbe Milliarde Multiplikationen pro Sekunde machen, sind die Multiplikationen nicht Ihr Flaschenhals, und die Optimierung anderer Teile des Codes wird ergiebiger sein.
Tags und Links java optimization