2016-02-22 11 views
5

Ich habe an einer portablen C-Bibliothek gearbeitet, die Bildverarbeitung durchführt.Wie kann ich Leistungsoptimierungen in C testen?

Ich habe ziemlich viel Zeit in ein paar Low-Level-Funktionen investiert, um GCC-Auto-Vectorization (SSE und/oder AVX je nach Zielprozessor) -Modus zu nutzen und trotzdem einen etwas portablen C-Code (Erweiterungen) beizubehalten verwendet: restrict und __builtin_assume_aligned).

Jetzt ist es Zeit, den Code auf Windows (MSVC-Compiler) zu testen. Aber davor würde ich gerne eine Art Unit-Test machen, um mich nicht in den Fuß zu schießen und alle meine sorgfältig ausgewählten Anweisungen zu verlieren, um den GCC-Auto-Vektorisierungs-Code wie er ist zu erhalten.

Ich könnte einfach #ifdef/#endif die ganze Körperfunktion, aber ich denke an eine langfristige Lösung, die auf Compiler-Update (s) jeder Regression erkennen würde.

Ich bin ziemlich sicher mit Unit-Tests (es gibt Tonnen von guten Rahmenbedingungen da draußen), aber ich bin viel weniger zuversichtlich mit Unit-Tests von solchen Low-Level-Funktionalität. Wie integriert man Performance-Unit-Tests in CI-Services wie Jenkins?

PS: Ich möchte hartcodierte Timing Ergebnisse basierend auf einem bestimmten Prozessor zu vermeiden, speichern, zB:

// start timer: 
gettimeofday(&t1, NULL); 
// call optimized function: 
... 
// stop timer: 
gettimeofday(&t2, NULL); 
// hard code some magic number: 
if(t2.tv_sec - t1.tv_sec > 42) return EXIT_FAILURE; 
+1

Haben Sie nicht optimierte (generische) Funktionen? Es wäre besser, die Ausführungszeit mit ihnen zu vergleichen ... was bedeutet, dass "t_opt" kleiner als "t_non_opt" ist ... aber selbst das ist keine 100% ige Garantie. Andere Prozesse können zufälligen Festplattenzugriff parallel ausführen, Ihr Test könnte jederzeit beendet werden ... und eine Menge anderer Dinge könnten nicht in Ihren Tests passieren ... – zaufi

+0

Worauf zielen Sie? Möchten Sie sicherstellen, dass Ihr Code nach Ihren Änderungen korrekt bleibt (dann würden Sie Komponententests durchführen) oder möchten Sie die Leistung des resultierenden Codes überprüfen (der etwas anders ist und auf verschiedene Arten angesprochen werden kann)? In letzterem Fall möchten Sie vielleicht sogar den generierten Assembler-Code ausdrucken, um ihn mit Ihren Erwartungen zu vergleichen. –

+0

@DirkHerrmann das ist der springende Punkt! Wie drucke ich "tragbaren" Assemblercode? Dies hängt von der exakten gcc-Version ab, danke für weitere Details, wenn Sie mit dem Generieren von Assembler-Code vertraut sind. – malat

Antwort

-1


Unter der Annahme, dass Sie einen guten Grund haben MSVC zu verwenden, wenn ich Sie wäre Ich würde bei einer Methode so niedrig wie möglich bleiben, um periphere Interferenz (en) zu verringern.
Selbst wenn Sie lieber ein geeignetes Framework zum Testen verwenden würden, bietet eine einfache Schleife, die Ihre Schlüsselfunktionen mit vorgegebenen Parametern und mit Zeitgebern an den richtigen Stellen aufruft, zuverlässigere Ergebnisse als Alternativen. Wenn Sie einige grundlegende Mittelwert und eine Standardabweichung von Timing-Ergebnisse berechnen kann, würden Sie ein sehr klares Bild davon haben, was mit Leistung los ist, wo und wann es wird langsamer oder schneller als es tun sollten etc ...

1

Ihr Problem besteht im Wesentlichen aus zwei Teilen:

  1. Was ist der beste Weg zur Leistungsbewertung Ihres sorgfältig optimierten Codes?

  2. Wie die Ergebnisse der Vergleiche zu vergleichen, so dass Sie, wenn Änderungen Code erkennen und/oder Compiler-Updates der Leistung des Codes betroffen

Der google benchmark Rahmen einen vernünftigen Ansatz zur Problem # bieten könnte 1. Es ist C++, aber das würde Sie nicht davon abhalten, Ihre C-Funktionen von dort aufzurufen.

Diese Bibliothek kann zusammenfassende Berichte in verschiedenen Formaten erstellen, einschließlich JSON und guter alter CSV. Sie können dafür sorgen, dass diese irgendwo pro Lauf gespeichert werden.

Sie könnten dann ein einfaches Skript perl/python/etc schreiben, um die Ergebnisse der Benchmarks zu vergleichen und den Alarm auszulösen, wenn sie um mehr als einen Schwellenwert abweichen.

Eine Sache, auf die Sie achten müssen, ist das Potenzial für Rauschen in Ihren Ergebnissen, das durch Variablen wie die Belastung des Systems, das den Test ausführt, verursacht wird. Sie haben nicht viel über die Umgebung gesagt, in der Sie die Tests ausführen, aber wenn es sich z. B. um eine VM auf einem Host mit anderen VMs handelt, können die Testergebnisse von den anderen VMs abweichen.

CI-Frameworks wie Jenkins ermöglichen es Ihnen, die Aktionen, die beim Ausführen von Tests ausgeführt werden sollen, zu erstellen. Daher sollte es relativ einfach sein, diesen Ansatz in solche Frameworks zu integrieren.

1

Eine Möglichkeit, die Leistung auf einfache und wiederholbare Weise zu messen, wäre, einen Benchmarking-Unit-Test über Valgrind/Callgrind durchzuführen. Das gibt Ihnen eine Anzahl von Metriken: CPU-Zyklen, Befehls- und Datenlese- und -schreibtransaktionen (bei verschiedenen Cachetiefen), busblockierende Transaktionen, usw. Sie müssten diese Werte nur gegen einen bekanntermaßen guten Startwert prüfen .

Valgrind ist wiederholbar, weil es die Ausführung des Codes emuliert. Es ist natürlich (viel) langsamer als die direkte Ausführung des Codes, aber das macht es unabhängig von der Systemlast usw.

Wo Valgrind nicht verfügbar ist, wie in Windows (obwohl es erwähnt Valgrind + Wein + Windows-Programme Unter Linux) ist dynamoRIO eine Option. Es bietet ähnliche Werkzeuge wie Valgrind, wie einen Anweisungszähler und einen Speicher- und Cache-Verwendungsanalysator. (Auch unter Linux verfügbar und scheinbar zum OS X halb portiert)

+1

nicht auf Windows portierbar, aber gibt zumindest viel mehr Details als nur das Testtiming. – malat

+0

Es wird erwähnt Valgrind + Wein Setups, aber ja, das könnte kompliziert werden. – hmijail

+0

@malat, wenn du noch daran arbeitest, habe ich gerade etwas gefunden, das Valgrinds verschiedenen Tools für Windows entspricht: http://dynamorio.org/ (überprüfe das "Instruction Counting Tool Inscount" und "Multi-Process Online-Cache-Simulator drcachesim ") – hmijail