ulmBLAS: Benchmark Suite
Nachdem wir eine eigene, standardkonforme Referenzimplementierung haben werden wir als nächstes eine Benchmark Suite dazu aufsetzen. Damit ist das Fundament für eine nachfolgende Optimierungsphase gelegt.
Good Artists Create, Great Artists Steal
Wie in der Vorlesung erwähnt kann man bei Benchmarks viel falsch machen. Und vielen Benchmarks, die im Netz veröffentlicht sind darf man nicht trauen:
-
Eventuell merkt der Compiler, dass Ergebnisse eines Durchlaufs gar nicht benutzt werden und optimiert die Durchläufe einfach weg. Damit erhält man natürlich tolle Ergebnisse!
-
Werden mehrfach die gleichen Routinen aufgerufen, dann sind die Caches eventuell schon mit den Daten befüllt, die benötigt werden. Damit enthalten Messungen nicht wirklichen den Aufwand für Speicherzugriffe. Man muss deshalb nach jeder Messung die Caches löschen (“Cache Flush”).
Die einfachste Lösung ist es einen Benchmark zu benutzen der das alles richtig macht und dem jeder vertraut. Ein solcher Benchmark ist zum Beispiel der von ATLAS! Deshalb habe ich aus der recht komplexen Bibliothek ganz schamlos diesen Teil herausgenommen und in das Unterverzeichnis bench/ gelegt.
Ab Tag v0.0.11 ist der ATLAS Benchmark enthalten
Wie der Benchmark Funktioniert
Es werden zwei BLAS Implementierungen gegeneinander getestet:
-
Die erste Implementierung muss ein Fortran 77 Interface anbieten.
-
Die zweite Implementierung muss ein C Interface anbieten bei dem die Funktionsnamens ein ATL_ Präfix haben. Das heisst ATL_copy statt unserem ULM_copy.
Bemerkung: Damit der ATLAS Benchmark funktioniert muss die BLAS Implementierung noch Funktionen rotm und rotmg definieren. Es reicht, wenn ihr dafür Stubs schreibt.
Aufgabe:
-
Wir erzeugen ein “Fake ATLAS” indem wir in “ulmblas.h” das Präfix auf “ATL_” ändern. Im Tag v0.0.11 wurde das übrigens so gelöst, dass
-
sowohl ein libulmblas.a wie zuvor erzeugt wird (mit ULM_copy usw.)
-
als auch ein “Fake ATLAS” libatlulmblas.a (mit ATL_copy usw.)
-
-
Das bench/ Verzeichnis in euer Projekt kopieren.
-
Das Makefile dort anschauen.
Hier eine Demo wie das am Ende alles aussehen könnte:
$shell> git clone https://github.com/michael-lehn/ulmBLAS.git fatal: destination path 'ulmBLAS' already exists and is not an empty directory. $shell> cd ulmBLAS $shell> git checkout tags/v0.0.11 HEAD is now at b7decd4... Pimped some of the makefiles $shell> make for dir in level1 refblas test bench; do make -C $dir; done make[1]: Nothing to be done for `all'. make[1]: Nothing to be done for `all'. make[1]: Nothing to be done for `all'. make[1]: `xdl1blastst' is up to date. $shell> cd bench $shell> ./xdl1blastst ./xdl1blastst --------------------- AXPY ----------------------- TST# N ALPHA INCX INCY TIME MFLOP SpUp TEST ==== ==== ===== ==== ==== ====== ===== ===== ===== 0 100 1.0 1 1 0.00 66.7 1.00 ----- 0 100 1.0 1 1 0.00 100.0 1.50 PASS 1 200 1.0 1 1 0.00 400.0 1.00 ----- 1 200 1.0 1 1 0.00 200.0 0.50 PASS 2 300 1.0 1 1 0.00 300.0 1.00 ----- 2 300 1.0 1 1 0.00 300.0 1.00 PASS 3 400 1.0 1 1 0.00 400.0 1.00 ----- 3 400 1.0 1 1 0.00 400.0 1.00 PASS 4 500 1.0 1 1 0.00 333.3 1.00 ----- 4 500 1.0 1 1 0.00 500.0 1.50 PASS 5 600 1.0 1 1 0.00 400.0 1.00 ----- 5 600 1.0 1 1 0.00 600.0 1.50 PASS 6 700 1.0 1 1 0.00 466.7 1.00 ----- 6 700 1.0 1 1 0.00 350.0 0.75 PASS 7 800 1.0 1 1 0.00 533.3 1.00 ----- 7 800 1.0 1 1 0.00 400.0 0.75 PASS 8 900 1.0 1 1 0.00 450.0 1.00 ----- 8 900 1.0 1 1 0.00 450.0 1.00 PASS 9 1000 1.0 1 1 0.00 500.0 1.00 ----- 9 1000 1.0 1 1 0.00 400.0 0.80 PASS 10 tests run, 10 passed
Eigene Benchmarks
Mit xdl1blastst -h könnt ihr sehen was und wie man alles Testen kann.
Aufgaben:
-
Ändert die Größe des Problems.
-
Testet auch die anderen Funktionen.
Visualisierung der Benchmarks
Damit man die Ergebnisse in gnuplot benutzen kann wenden wir etwas Shell Magie an und erzeugen die zwei Dateien bench.1.axpy und bench.2.axpy wie folgt:
$shell> ./xdl1blastst > report.axpy $shell> grep "\ \-\-\-\-\-$" report.axpy | (while read line; do line=($line); echo "${line[1]} ${line[6]}"; done) > bench.1.axpy $shell> grep "PASS" report.axpy | (while read line; do line=($line); echo "${line[1]} ${line[6]}"; done) > bench.2.axpy
Mit cat bench.1.axpy könnt ihr deren Inhalt anschauen. In gnuplot könnt ihr mit
dies dann darstellen.