Ein guter Ausgangspunkt ist das großartige Buch The Science of Programming Matrix Computations von Robert A. van de Geijn und Enrique S. Quintana-Ortí. Sie bieten eine kostenlose Download-Version.
BLAS ist in drei Ebenen unterteilt:
Stufe 1 definiert eine Reihe von linearen Algebra-Funktionen, die nur mit Vektoren arbeiten. Diese Funktionen profitieren von der Vektorisierung (z. B. von der Verwendung von SSE).
Funktionen der Ebene 2 sind Matrixvektoroperationen, z. B. ein Matrixvektorprodukt. Diese Funktionen könnten in Form von Level1-Funktionen implementiert werden. Sie können jedoch die Leistung dieser Funktionen steigern, wenn Sie eine dedizierte Implementierung bereitstellen, die eine Multiprozessorarchitektur mit gemeinsam genutztem Speicher verwendet.
Level 3-Funktionen sind Operationen wie das Matrix-Matrix-Produkt. Auch hier können Sie sie in Bezug auf Level2-Funktionen implementieren. Level3-Funktionen führen jedoch O (N ^ 3) -Operationen für O (N ^ 2) -Daten aus. Wenn Ihre Plattform über eine Cache-Hierarchie verfügt, können Sie die Leistung steigern, wenn Sie eine dedizierte Implementierung bereitstellen, die cache-optimiert / cache-freundlich ist . Dies ist im Buch gut beschrieben. Der Hauptschub der Level3-Funktionen liegt in der Cache-Optimierung. Dieser Boost übertrifft den zweiten Boost aufgrund von Parallelität und anderen Hardwareoptimierungen erheblich.
Übrigens sind die meisten (oder sogar alle) Hochleistungs-BLAS-Implementierungen NICHT in Fortran implementiert. ATLAS ist in C implementiert. GotoBLAS / OpenBLAS ist in C und seine leistungskritischen Teile in Assembler implementiert. In Fortran ist nur die Referenzimplementierung von BLAS implementiert. Alle diese BLAS-Implementierungen bieten jedoch eine Fortran-Schnittstelle, sodass sie mit LAPACK verknüpft werden kann (LAPACK erhält seine gesamte Leistung von BLAS).
Optimierte Compiler spielen in dieser Hinsicht eine untergeordnete Rolle (und für GotoBLAS / OpenBLAS spielt der Compiler überhaupt keine Rolle).
IMHO keine BLAS-Implementierung verwendet Algorithmen wie den Coppersmith-Winograd-Algorithmus oder den Strassen-Algorithmus. Ich bin mir über den Grund nicht ganz sicher, aber das ist meine Vermutung:
- Möglicherweise ist es nicht möglich, eine Cache-optimierte Implementierung dieser Algorithmen bereitzustellen (dh Sie würden mehr verlieren als gewinnen).
- Diese Algorithmen sind numerisch nicht stabil. Da BLAS der Rechenkern von LAPACK ist, ist dies ein No-Go.
Bearbeiten / Aktualisieren:
Das neue und bahnbrechende Papier zu diesem Thema sind die BLIS-Papiere . Sie sind außergewöhnlich gut geschrieben. Für meine Vorlesung "Software-Grundlagen für High Performance Computing" habe ich das Matrix-Matrix-Produkt nach deren Arbeit implementiert. Eigentlich habe ich mehrere Varianten des Matrix-Matrix-Produkts implementiert. Die einfachste Variante ist vollständig in einfachem C geschrieben und enthält weniger als 450 Codezeilen. Alle anderen Varianten optimieren lediglich die Schleifen
for (l=0; l<MR*NR; ++l) {
AB[l] = 0;
}
for (l=0; l<kc; ++l) {
for (j=0; j<NR; ++j) {
for (i=0; i<MR; ++i) {
AB[i+j*MR] += A[i]*B[j];
}
}
A += MR;
B += NR;
}
Die Gesamtleistung des Matrix-Matrix-Produkts hängt nur von diesen Schleifen ab. Etwa 99,9% der Zeit wird hier verbracht. In den anderen Varianten habe ich Intrinsics und Assembler-Code verwendet, um die Leistung zu verbessern. Sie können das Tutorial sehen, das alle Varianten hier durchläuft:
ulmBLAS: Tutorial zu GEMM (Matrix-Matrix-Produkt)
Zusammen mit den BLIS-Papieren wird es ziemlich einfach zu verstehen, wie Bibliotheken wie Intel MKL eine solche Leistung erzielen können. Und warum spielt es keine Rolle, ob Sie Zeilen- oder Spalten-Hauptspeicher verwenden!
Die letzten Benchmarks sind hier (wir haben unser Projekt ulmBLAS genannt):
Benchmarks für ulmBLAS, BLIS, MKL, openBLAS und Eigen
Noch eine Bearbeitung / Aktualisierung:
Ich habe auch ein Tutorial darüber geschrieben, wie BLAS für numerische lineare Algebra-Probleme wie das Lösen eines linearen Gleichungssystems verwendet wird:
Hochleistungs-LU-Faktorisierung
(Diese LU-Faktorisierung wird beispielsweise von Matlab zum Lösen eines linearen Gleichungssystems verwendet.)
Ich hoffe, Zeit zu finden , um das Tutorial zu erweitern und zu beschreiben und zu demonstrieren, wie eine hoch skalierbare parallele Implementierung der LU-Faktorisierung wie in PLASMA realisiert werden kann .
Ok, los geht's: Codieren einer Cache-optimierten parallelen LU-Faktorisierung
PS: Ich habe auch einige Experimente zur Verbesserung der Leistung von uBLAS durchgeführt. Es ist eigentlich ziemlich einfach, die Leistung von uBLAS zu steigern (ja, mit Worten spielen :)):
Experimente zu uBLAS .
Hier ein ähnliches Projekt mit BLAZE :
Experimente mit BLAZE .