Christian Seiler: Objektorientierung - Eine Fehlentwicklung der Informatik?

Beitrag lesen

Hallo Tom,

[...] falsche Vorgabe der freien Portierbarkeit, die im Falle von z.B. C++ zu einer extrem mangelhaften Unterstützung der äußerst gängigen Plattform Intel-8086ff (oder auch anderer) führt. Die Hardwarefähigkeiten werden hier in keiner Weise vollständig und/oder oft nur durch die Hintertür ausgenutzt. Das sorgt dafür, dass trotz erheblich gewachsener Rechenleistung der PCs hier sehr viel Zeit mit Umwegen verdödelt wird, also keinesfalls die volle Leistungsfähigkeit der Hardware ausgenutzt werden kann.

Ich möchte Dich auf das Projekt Eigen aufmerksam machen. Das ist eine C++-Bibliothek für lineare Algebra, d.h. Operationen mit Matrizen und Vektoren. Diese Bibliothek zeichnet sich dadurch aus, dass sie die Möglichkeiten von C++-Template-Metaprogrammierung vollständig ausreizt.

Normale Bibliotheken für lineare Algebra wie BLAS/LAPACK stellen eine ganze Reihe von spezialisierten Funktion bereit, die bestimmte hochspezifische Aufgaben erledigen, die selbst noch einmal durch eine Reihe von hochspezialisierten Parametern beeinflusst werden können. Siehe zum Beispiel die Übersicht über BLAS-Routinen im LUG. Wenn irgend eine spezifische Kombination nun aber nicht implementiert ist in dieser Bibliothek, muss man sich selbst überlegen, wie man das am effizientesten implementiert. Und dann reizt man Prozessorfeatures für Vektorisierung (SSE) usw. eben in der Regel nicht oder nur unzureichend (wenn der Compiler automatisch solchen Code generiert) aus.

Der Ansatz von Eigen ist ein völlig anderer: Anstelle, dass man eine Bibliothek hat, die Routinen enthält, die für alle möglichen Spezialfälle ausgelegt sind, nutzt man C++-Template-Metaprogrammierung. Eigen besteht *ausschließlich* aus C++-Headerdateien. Wenn man diese einbindet und Eigen nutzt, dann wird zur Compilezeit auf Grund der C++-Templates an der Stelle ein hochoptimierter Code *generiert*.

Das heißt: Man verwendet Objektorientierung. Eine Matrix ist eine Klasse. Ein Vektor ist eine Klasse. Operationen sind als überladene Operatoren und Methoden dieser Klassen definiert. Der Sourcecode ist damit extrem leserlich. Wenn man dann allerdings so etwas schreibt wie

vektor2 = matrix * vektor1;

und das dann mit dem Compiler übersetzt, dann wird durch die C++-Templates an der Stelle zur Compilezeit hochoptimierter Assembler-Code erzeugt, der diese Operation mit allen modernen Features des Prozessors durchführt.

Klar, für so etwas simples wie das Matrix-Vektor-Produkt gibt es natürlich auch optimierte Routinen in anderen Bibliotheken. Nur hat man dort das Problem, dass man sich erst mühsam immer wieder die Routinen aussuchen muss, die der effizienteste Weg sind, das Problem zu lösen. Und wenn es für einen Spezialfall gerade keine Routine gibt, dann muss man irgendwie drum herum arbeiten.

Eigen reduziert dieses Problem, in dem der optimierte Code zur Compilezeit generiert wird. Die Template-Logik von Eigen sorgt dafür, das in den allermeisten Fällen Code automatisch generiert wird, der für das *spezifische* Problem optimiert ist, das der Programmierer im Auge hatte. Die Bibliothek richtet sich also nach dem Programmierer. Und dennoch ist Eigen portabel, es nutzt Compiler-Erweiterungen nur in Verbindung mit einem Fallback auf Standard-C++-Features. Die Logik erkennt zur Compilezeit, welche Assembler-Befehle es für den Zielprozessor generieren darf und nutzt im Zweifelsfall die ganz normale FPU.

Daher ist Eigen eine eindrucksvoller Beweis, dass man die Vorteile von Objektorientierung nutzen kann, in dem man eine schöne, gut verständliche Syntax hat für die Operationen (und nicht irgendwelche Spezialisierungen von Routinen mit obskuren Namen aufrufen muss), gleichzeitig auch noch portabel sein kann, andererseits aber die Performancevorteile von modernen Prozessoren vollständig ausschöpfen kann. Und gerade die Template-Metaprogrammierung macht diese Effizienz in Verbindung mit einer guten Wartbarkeit der Software überhaupt erst möglich. Nicht jedes Sprachfeature, das eine zusätzliche Abstraktionsebene einführt, ist automatisch ein Performancekiller.

Viele Grüße,
Christian