Skip to content

Latest commit

 

History

History
104 lines (73 loc) · 3.22 KB

File metadata and controls

104 lines (73 loc) · 3.22 KB

Aufgaben zu Expression Templates

Zurück


Lösungen


Überblick

Aufgabe Beschreibung
Aufgabe 1 Das Skalarprodukt zweier Vektoren

Tabelle 1: Aufgaben zu Expression Templates.


Aufgabe 1: Das Skalarprodukt zweier Vektoren

Das skalare Produkt – auch inneres Produkt genannt – ist eine mathematische Verknüpfung von zwei Vektoren, bei der eine Zahl als Resultat herauskommt. Für zwei Vektoren a = (a1, a2, a3, ..., an) und b = (b1, b2, b3, ..., bn) berechnet sich das Ergebnis zu a1 * b1 + a2 * b2 + ... + an * bn.

In einem sehr einfachen Ansatz könnte man in C++ das skalare Produkt zweier Vektoren a und b, wenn man diese in std::vector<T>-Objekten ablegt (sei T gleich float oder double), so berechnen:

T product{};
for (size_t i{}; i != a.size(); ++i) {
    product += (a[i]) * (b[i]);
}

Diese Realisierung hat allerdings zur Folge, dass – am Beispiel zweier Vektoren der Länge 5 detaillierter betrachtet – folgende Rechenschritte zur Ausführung gelangen:

T product = 0;
product += a[0] * b[0];
product += a[1] * b[1];
product += a[2] * b[2];
product += a[3] * b[3];
product += a[4] * b[4];

Wäre es nicht effizienter, wenn wir die Berechnung mit einer Realisierung anstreben könnten, die ohne die vielen (temporären) Additionen auf die Ergebnisvariable product auskommt? Also ganz einfach durch einen Ausdruck der Gestalt

T product = a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3] + a[4] * b[4];

Bei Vektoren mit im Vorneherein bekannter fester Länge könnte man diesen Ausdruck einfach wie gezeigt hinschreiben. Wie sieht es aus, wenn die Vektorenlänge zwar ebenfalls zur Übersetzungszeit bekannt ist, aber eben durch einen Bezeichner – sagen wir N – allgemein (zur Übersetzungszeit) gehalten wird? Mit Hilfe von „Loop Unrolling” bzw. C++ Metaprogramming kann man einen Ausdruck

T product = a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + ... a[N-1] * b[N-1];

vom Übersetzer erzeugen lassen!

Aufgabe: Erstellen Sie eine Klasseschablone ScalarProduct, die mit Hilfe von „Loop Unrolling” dieses Ziel erreicht.

Vergleichen Sie die Zeiten in der Ausführung an einem Beispiel. Auf meinem Rechner habe ich drei Realisierungen getestet:

  • Skalarprodukt mit std::vector-Objekten und Zugriff auf die Vektorenelemente mit dem Index-Operator operator[].
  • Skalarprodukt mit std::vector-Objekten und Zugriff auf die Vektorenelemente mit Iteratorenobjekten.
  • Skalarprodukt mit std::vector-Objekten und Expression Templates.

Ausgabe:

scalarProduct<double>(a, a): 385
Elapsed time: 5391 milliseconds.
scalarProductEx<double>(a.begin(), a.end(), a.begin()): 385
Elapsed time: 3406 milliseconds.
ScalarProduct<10, double>::result(a.cbegin(), a.cbegin()): 385
Elapsed time: 1102 milliseconds.

Lösungen


Zurück