F1: Welche Tools verwenden Sie für das Code-Profiling (Profiling, nicht Benchmarking)?
F2: Wie lange lässt du den Code laufen (Statistik: wie viele Zeitschritte)?
F3: Wie groß sind die Fälle (wenn der Fall in den Cache passt, ist der Solver um Größenordnungen schneller, aber dann werde ich die speicherbezogenen Prozesse vermissen)?
Hier ist ein Beispiel, wie ich es mache.
Ich trenne das Benchmarking (wie lange es dauert) vom Profiling (wie man es schneller macht). Es ist nicht wichtig, dass der Profiler schnell ist. Es ist wichtig, dass Sie wissen, was Sie beheben müssen.
Ich mag das Wort "Profiling" nicht einmal, weil es ein Bild wie ein Histogramm erzeugt, bei dem es für jede Routine eine Kostenleiste gibt, oder "Engpass", weil es impliziert, dass es nur einen kleinen Platz im Code gibt, der sein muss Fest. Beides setzt eine Art Timing und Statistik voraus, für die Sie Genauigkeit für wichtig halten. Es lohnt sich nicht, die Einsicht für die Genauigkeit des Timings aufzugeben.
Die Methode , die ich verwenden ist zufällig Pausieren, und es gibt eine vollständige Fallstudie und Dia - Show hier . Ein Teil der Weltanschauung zum Profiler-Engpass ist, dass man, wenn man nichts findet, nichts zu finden hat, und wenn man etwas findet und eine gewisse prozentuale Beschleunigung erreicht, erklärt man den Sieg und gibt auf. Profiler-Fans geben fast nie an, wie viel Geschwindigkeit sie erreichen, und die Anzeigen zeigen nur künstlich erfundene Probleme, die so gestaltet sind, dass sie leicht zu finden sind. Beim zufälligen Anhalten treten Probleme auf, unabhängig davon, ob sie einfach oder schwer sind. Wenn Sie dann ein Problem beheben, werden andere offengelegt, sodass der Vorgang wiederholt werden kann, um eine höhere Geschwindigkeit zu erzielen.
Nach meiner Erfahrung aus zahlreichen Beispielen funktioniert das folgendermaßen: Ich kann ein Problem finden (durch zufälliges Anhalten) und es beheben, indem ich eine Beschleunigung von einigen Prozent erhalte, z. B. 30% oder 1,3x. Dann kann ich es wieder tun, ein anderes Problem finden und es beheben, eine weitere Beschleunigung erzielen, vielleicht weniger als 30%, vielleicht mehr. Dann kann ich es mehrmals wiederholen, bis ich wirklich nichts mehr zu reparieren finde. Der ultimative Beschleunigungsfaktor ist das laufende Produkt der einzelnen Faktoren und kann in einigen Fällen erstaunlich groß sein - Größenordnungen.
INSERTED: Nur um diesen letzten Punkt zu veranschaulichen. Es gibt ein ausführliches Beispiel hier , mit Dia - Show und alle Dateien, die zeigen , wie ein Speedup von 730x wurde in einer Reihe von Problem Umzüge erreicht. Die erste Version benötigte 2700 Mikrosekunden pro Arbeitseinheit. Problem A wurde entfernt, wodurch die Zeit auf 1800 gesenkt und der Prozentsatz der verbleibenden Probleme um das 1,5-fache (2700/1800) vergrößert wurde. Dann wurde B entfernt. Dieser Prozess wurde durch sechs Iterationen fortgesetzt, was zu einer Beschleunigung um fast drei Größenordnungen führte. Die Profiling-Technik muss jedoch sehr effektiv sein. Wenn eines dieser Probleme nicht gefunden wird, dh wenn Sie einen Punkt erreichen, an dem Sie fälschlicherweise glauben, dass nichts mehr getan werden kann, wird der Prozess unterbrochen.
INSERTED: Um es anders auszudrücken, hier ist ein Diagramm des Gesamtbeschleunigungsfaktors, wenn aufeinanderfolgende Probleme beseitigt werden:
Für das Benchmarking von Q1 reicht also ein einfacher Timer aus. Für das "Profiling" verwende ich zufällige Pausen.
F2: Ich gebe ihm genug Arbeitslast (oder lege einfach eine Schleife darum), damit es lange genug läuft, um anzuhalten.
F3: Stellen Sie auf jeden Fall eine realistisch hohe Arbeitslast zur Verfügung, damit Sie keine Cache-Probleme verpassen. Diese werden als Beispiele im Code angezeigt, der die Speicherabrufe ausführt.