Angenommen, ich arbeite an einem wissenschaftlichen Code in C ++. In einer kürzlich mit einem Kollegen geführten Diskussion wurde argumentiert, dass Ausdrucksvorlagen eine wirklich schlechte Sache sein könnten, die möglicherweise die Kompilierbarkeit von Software nur auf bestimmten gcc-Versionen ermöglicht. Angeblich hat dieses Problem einige wissenschaftliche Codes betroffen, wie in den Untertiteln dieser Parodie des Untergangs angedeutet . (Dies sind die einzigen mir bekannten Beispiele, daher der Link.)
Andere Leute haben jedoch argumentiert, dass Ausdrucksvorlagen nützlich sind, weil sie, wie in diesem Artikel im SIAM Journal of Scientific Computing , zu Leistungssteigerungen führen können, indem die Speicherung von Zwischenergebnissen in temporären Variablen vermieden wird.
Ich weiß nicht viel über Template-Metaprogrammierung in C ++, aber ich weiß, dass dies ein Ansatz ist, der bei der automatischen Differenzierung und bei der Intervallarithmetik verwendet wird. So bin ich zu einer Diskussion über Ausdrucksvorlagen gekommen. Wann sollte ich C ++ - Ausdrucksvorlagen in der Informatik verwenden und wann sollte ich sie vermeiden, wenn sowohl die potenziellen Vorteile bei der Leistung als auch die potenziellen Nachteile bei der Wartung berücksichtigt werden (wenn dies überhaupt das richtige Wort ist)?
quelle
Antworten:
Mein Problem mit Ausdrucksvorlagen ist, dass sie eine sehr undichte Abstraktion sind. Sie schreiben sehr komplizierten Code, um eine einfache Aufgabe mit besserer Syntax zu erledigen. Wenn Sie jedoch den Algorithmus ändern möchten, müssen Sie sich mit dem unsauberen Code herumschlagen, und wenn Sie mit Typen oder Syntax in Konflikt geraten, erhalten Sie völlig unverständliche Fehlermeldungen. Wenn Ihre Anwendung perfekt einer Bibliothek zugeordnet ist, die auf Ausdrucksvorlagen basiert, ist dies möglicherweise eine Überlegung wert. Wenn Sie sich jedoch nicht sicher sind, würde ich empfehlen, nur normalen Code zu schreiben. Sicher, der Code auf hoher Ebene ist weniger hübsch, aber Sie können einfach das tun, was getan werden muss. Dies hat den Vorteil, dass die Kompilierungszeit und die Binärgrößen erheblich verkürzt werden und Sie aufgrund der Auswahl der Compiler- und Kompilierungsflags keine großen Leistungsunterschiede zu bewältigen haben.
quelle
Andere haben die Frage kommentiert, wie schwierig es ist, ET-Programme zu schreiben und wie komplex es ist, Fehlermeldungen zu verstehen. Lassen Sie mich das Problem der Compiler kommentieren: Es ist wahr, dass vor einiger Zeit eines der großen Probleme darin bestand, einen Compiler zu finden, der dem C ++ - Standard entspricht, damit alles funktioniert und es portabel funktioniert. In der Folge haben wir viele Fehler gefunden - ich habe 2-300 Fehlerberichte in meinem Namen, die über gcc, Intel icc, IBM xlC und Portland's pgicc verteilt sind. Folglich ist das deal.II-Konfigurationsskript ein Repository für eine große Anzahl von Compiler-Bug-Tests, hauptsächlich im Bereich von Vorlagen, Friend-Deklarationen, Namespaces usw.
Es stellt sich jedoch heraus, dass die Compiler-Macher ihre Sache wirklich gut gemacht haben: Heute bestehen GCC und ICC alle unsere Tests und es ist einfach, Code zu schreiben, der zwischen den beiden portierbar ist. Ich würde sagen, dass die ggA nicht weit hinterherhinkt, aber es gibt eine Reihe von Macken, die im Laufe der Jahre nicht zu verschwinden scheinen. Auf der anderen Seite ist xlC eine ganz andere Geschichte - sie beheben alle 6 Monate einen Fehler, aber trotz jahrelanger Einreichung von Fehlerberichten ist der Fortschritt extrem langsam und xlC konnte deal.II noch nie erfolgreich kompilieren.
Dies alles bedeutet Folgendes: Wenn Sie sich an die beiden großen Compiler halten, können Sie davon ausgehen, dass sie nur heute funktionieren. Da die meisten Computer und Betriebssysteme heutzutage normalerweise mindestens einen haben, reicht das aus. Die einzige Plattform, auf der es schwieriger ist, ist BlueGene, wo der System-Compiler normalerweise xlC ist, mit all seinen Fehlern.
quelle
Ich habe vor langer Zeit ein wenig mit ETs experimentiert, als, wie Sie sagten, Compiler noch mit ihnen zu kämpfen hatten. Ich habe die Blitzbibliothek für lineare Algebra in einem Code von mir verwendet. Das Problem war dann, den guten Compiler zu bekommen und da ich kein perfekter C ++ - Programmierer bin, die Compiler-Fehlermeldungen zu interpretieren. Letzteres war einfach unüberschaubar. Der Compiler würde im Durchschnitt etwa 1000 Zeilen mit Fehlermeldungen erzeugen. Auf keinen Fall konnte ich meinen Programmierfehler schnell finden.
Weitere Informationen finden Sie auf der oonumerics- Webseite (es gibt die Abläufe von zwei ET-Workshops).
Aber ich würde weit weg von ihnen bleiben ...
quelle
Das Problem beginnt bereits mit dem Begriff "Ausdrucksvorlagen (ET)". Ich weiß nicht, ob es eine genaue Definition dafür gibt. Aber in seiner allgemeinen Verwendung verbindet es irgendwie "wie man lineare Algebra-Ausdrücke codiert" und "wie es berechnet wird". Beispielsweise:
Sie codieren die Vektoroperation
Und es wird von einer Schleife berechnet
Meiner Meinung nach sind dies zwei verschiedene Dinge, die entkoppelt werden müssen: (1) ist eine Schnittstelle und (2) eine mögliche Implementierung. Ich meine, das ist bei der Programmierung üblich. Sicher (2) mag eine gute Standardimplementierung sein, aber im Allgemeinen möchte ich in der Lage sein, eine spezialisierte, dedizierte Implementierung zu verwenden. Zum Beispiel möchte ich, dass eine Funktion wie
werde gerufen wenn ich codiere (1). Vielleicht benutzt (3) nur intern eine Schleife wie in (2). Abhängig von der Vektorgröße können andere Implementierungen jedoch effizienter sein. Auf jeden Fall kann ein Experte für hohe Leistung (3) so viel wie möglich implementieren und optimieren. Wenn also (1) nicht auf einen Aufruf von (3) abgebildet werden kann, dann vermeide ich lieber den syntaktischen Zucker von (1) und rufe sofort (3) direkt auf.
Was ich beschreibe, ist nichts Neues. Im Gegenteil, es ist die Idee hinter BLAS / LPACK:
Wenn der Umfang von BLAS nicht ausreicht (z. B. keine Funktion wie (3) bereitstellt), kann der Umfang von BLAS erweitert werden. So realisiert dieser Dinosaurier aus den 60er und 70er Jahren mit seinem Steinzeitwerkzeug eine saubere und orthogonale Trennung von Schnittstelle und Implementierung. Es ist schon komisch, dass (die meisten) numerischen C ++ - Bibliotheken diese Softwarequalität nicht erreichen. Obwohl die Programmiersprache selbst so viel ausgefeilter ist. Kein Wunder also, dass BLAS / LAPACK noch am Leben und aktiv entwickelt ist.
Meiner Meinung nach sind ETs also nicht böse an sich. Aber wie sie üblicherweise in numerischen C ++ - Bibliotheken verwendet werden, verschaffte ihnen in wissenschaftlichen Rechenkreisen einen schlechten Ruf.
quelle