PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [c++] valarray halten nicht was sie versprechen



Akleson
08-05-2006, 11:09
Hallo

Ich wollte für ein Bildverarbeitungsproblem (für ein Echtzeitsystem) Berechnungen, die derzeit mit vector laufen auf valarray umstellen. In verschiedenen Büchern und Texten im Web werden diese als für numerische Berechnungen optimierte "Arrays" angepriesen. Leider kann ich das bei mir hier nicht ganz nachvollziehen. Im Gegenteil ich hab hier ein einfaches Beispiel bei dem sie deutlich langsamer sind.

Hier ist mal mein kleines Testprogramm

#include <iostream>
#include <valarray>
#include <vector>
#include <cstdlib>

{ ... schnipp schnapp .. }

int main() {

{ ... schnipp schnapp .. }

vector<float> vFloat(tSize);
vector<int> vInt(tSize);

tTime.set();
for (int r = 0; r != Runs; ++r) {
for (size_t i = 0; i != vFloat.size(); ++i) {
vFloat[i] *= fFloat;
}
}
tDur.set(tTime);
cout << endl;
cout << "Vector: vector<float> elementweise mit float mulitpliziert" << endl;
cout << "Vector: size=" << vFloat.size() << " runs=" << Runs << " duration=" << tDur.get() << endl;

tTime.set();
for (int r = 0; r != Runs; ++r) {
for (size_t i = 0; i != vInt.size(); ++i) {
vInt[i] *= 4;
vInt[i] /= 5;
}
}
tDur.set(tTime);
cout << endl;
cout << "Vector: vector<int> elementweise * 4 / 5" << endl;
cout << "Vector: size=" << vInt.size() << " runs=" << Runs << " duration=" << tDur.get() << endl;

//################################################## ####

valarray<float> vaFloat(tSize);
valarray<int> vaInt(tSize);

tTime.set();
for (int r = 0; r != Runs; ++r) {
vaFloat *= fFloat;
}
tDur.set(tTime);
cout << endl;
cout << "Valarray: valarray<float> elementweise mit float mulitpliziert" << endl;
cout << "Valarray: size=" << vaFloat.size() << " runs=" << Runs << " duration=" << tDur.get() << endl;

tTime.set();
for (int r = 0; r != Runs; ++r) {
vaInt *= 4;
vaInt /= 5;
}
tDur.set(tTime);
cout << endl;
cout << "Valarray: valarray<int > elementweise * 4 / 5" << endl;
cout << "Valarray: size=" << vaInt.size() << " runs=" << Runs << " duration=" << tDur.get() << endl;
}


Ich habe dieses auf ein Linux PC (Pentium 4) compiliert (gcc 3.4.3,-O2) und ausgeführt. Das Ergebniss war unerwartet:


Vector: vector<float> elementweise mit float mulitpliziert
Vector: size=1000000 runs=100 duration=2047.86

Vector: vector<int> elementweise * 4 / 5
Vector: size=1000000 runs=100 duration=2130.25

Valarray: valarray<float> elementweise mit float mulitpliziert
Valarray: size=1000000 runs=100 duration=2051.39

Valarray: valarray<int > elementweise * 4 / 5
Valarray: size=1000000 runs=100 duration=7566.39

also bei Int werten ist valarray um den Faktor 4 langsamer als ein von Hand multiplizierter Vektor. Und auch bei der Float Variante gewinne ich keinerlei Zeit. Ich hab auch mit Optionen wie -msse u.ä. oder -march probiert mit dem gleichen Ergebnis.

Kann mir evtl jemand sagen, ob ich etwas falsch verstanden habe oder einen logischen Denkfehler unterliege? Ich kann mir diese Ergebnisse nur noch erklären mit einer schlechten Implementation von valarrays in der mir vorliegenden Version.

Gruss Hannes

SeeksTheMoon
24-05-2006, 10:49
"Die Standardbibliothek enthält zur Unterstützung numerischer Operationen auf großen Feldern typgleicher Elemente den Container valarray. Man kann ihn sich wie eine Version von vector vorstellen, dessen Länge sich einmalig dynamisch festlegen lässt, der aber daraufhin optimiert ist, dass sich diese Länge später nicht mehr ändert."

heißt es im Netz. Ich lese keinen Hinweis, dass es für Zahlenwerte optimiert ist.

Lin728
24-05-2006, 16:29
Eigentlich stimmts ja, der Compiler weiß ja dass auf alle Elemente die selbe Operation ausgeführt werden soll und sollte darauf hin Optimierungen durchführen können (z.B. vektorisieren) ohne den Quellcode zuerst kompliziert analysieren zu müssen.

Ich würds zuerst einmal mit gcc-4.1 ausprobieren und wenns da nicht funtzt mal den icc-9.1 auspribieren auf der gcc mailingliste nachfragen wieso's der kann und der gcc nicht ;) .

peschmae
24-05-2006, 17:37
heißt es im Netz. Ich lese keinen Hinweis, dass es für Zahlenwerte optimiert ist.

Im Stroustroup steht da schon anderes. Da hat der OP schon recht, valarray sollte diesbezüglich optimiert sein.

MfG Peschmä

Akleson
24-05-2006, 23:31
Wir haben verschiedene Compiler getestet. Leider sind wir auf den gcc angewiesen. Sobald wir beim kompilieren -O2 eingeschaltet haben, hatten die Valarrays verloren. Stellenweise wurden sie sogar langsamer. Erst ab einer größe von > 500MB wurden sie wieder schneller.

Ich dachte dass die valarray gerade durch Vektoriesierung optimiert werden können. Dazu stehen meiner Meinung auch die Prozessor Features SSE und SSE2.

Schade das es in der Realität nicht ganz so schön ist.
gruss Hannes

Detrius
25-05-2006, 00:28
Ist vielleicht Blitz++ (http://www.oonumerics.org/blitz/) was für Dich?

Joghurt
29-05-2006, 10:14
Ich dachte dass die valarray gerade durch Vektoriesierung optimiert werden können. Dazu stehen meiner Meinung auch die Prozessor Features SSE und SSE2.Kompiliert ihr denn auch mit
-march=athlonxp -msse2 -mfpmath=sse -O2(Statt "athlonxp" natürlich den entsprechenden Prozzi einsetzen)

Bzw: Wurde die STL-Library auch mit diesen Optionen compiliert? Debians' vorgefertigte Pakete z.B. sind immer für den 80386 optimiert.