optimierung: 2mal das gleiche == nicht das selbe...
-
Hallo allerseits,
seit langem mal wieder Spielzeit zu hause mit Bildverarbeitungsalgos, templates und openMP und C++0x mit dem g++.
folgende Zeile
value_type filterValue = (*itBeg).operator[](k);sollte doch eigentlich äquivalent zu
const FilterContainer& vFilter = *itBeg; value_type filterValue = vFilter[k];sein ist sie auch rein vom Ergebnis, aber variante 2 ist ein gutes stueck schneller. Ich denke das ist kompilerspeziefisch - hab mir das disassembly noch nicht angeschaut :). Eine logische Erklaerung, warum das 2te besser zu optimieren sein sollte habe ich nicht.
ausserdem habe ich mal ausprobiert:
const FilterContainer vFilter( *itBeg );
was erschreckend langsam war, weil kopiert wird - dachte, das er das durch copy elision komplett weg bekommt....
danke und Viele Gruesse,
Tobias
-
peinlich peinlich - hat sich erledigt: die Streuung der Messung ist wohl irgendwie ziemlich gross...
haette einfach mehrere Durchlaeufe machen sollen - ist beides identisch - mein Weltbild wieder gerade...
-
ok, wieter gehts (hoffentlich nicht wieder nur weil ich bloedsinn verzapft habe):
ich hab jetzt meinen Algo soweit aufgesplittet das er mit und ohne openmp halbwegs fix funktioniert. Der openMP part ist sozusagen "davorgebaut"
template<typename TIn, typename TOut, typename TImageOP> void executeImageOP( PixelIterator<TIn> itStartIn, PixelIterator<TIn> itEndIn, PixelIterator<TOut> itOutStart, TImageOP imageOP ) { const int iNumCPUs = 2; int k =0; typedef typename PixelIterator<TIn>::ItertorContainer PixelIterCntIn; typedef typename PixelIterator<TOut>::ItertorContainer PixelIterCntOut; PixelIterCntIn itStartInPart( itStartIn.partition( iNumCPUs ) ); PixelIterCntOut itStartOutPart( itOutStart.partition( iNumCPUs ) ); #pragma omp parallel for for( k=0;k<iNumCPUs;k++ ) { //lets do the real calculation... imageOP( itStartInPart[k], itStartInPart[k].end(), itStartOutPart[k] ); } } }sozusagen splitte ich die daten selber mit meiner eigenen partition methode meines iterators, der ein array von iteratoren zurueckgiebt, die alle verschiedene Bereiche des Bildes beackern, ohne sich in die quere zu kommen. Deshalb kann ich auch getrost auf lahme syncs verzichten.
Frage: D.d. ich bin wohl drauf angewiesen die Zahl der Cores/CPUs abzufragen, oder giebts da was besseres. Denke das ich sonst selbst irgendwelche komischen #ifdefs setzen muss, wenn es auch auf ollen compilern laufen soll...
Skaliert uebrigens ganz gut: auf meiner Dualcore kiste annaehern faktor 2 zum "single" core algo.
Laesst sich auch super vergleichen, weil der algo der Gleiche ist nur halt mit anderen iterator ranges gefuettert wird.Danke und Viele Gruesse,
Tobias
-
Ich weiß nicht ob ich genau verstanden habe was du da machst, aber ich glaube das was du da mit der partition Methode machst, macht eigentlich
omp parallel forautomatisch. Der kann auch mit random access Iteratoren, kannst also eigentlich einfach#pragma omp parallel for for( ;first != last; ++first ) // ...Anzahl der logischen CPUs wählt er auch automatisch.
-
das generelle problem mit openmp ist doch, dass er iteratoren kaum sinnvoll parallelisieren kann. Nach meinen messungen macht es fuer viele Parallelisierungen ueberhaupt nur sinn, wenn man sync points weitestgehend vermeiden kann, weil syncs ganz leicht den performancegewinn wieder auffressen.
Das hatte zur folge, dass mein code zumindest auf 2 cores kaum schneller war als die Singlecore variante. Jede Bildverarbeitungsfunktion gehorcht im prinzip dem folgenden muster:imageOP( InputIteratorStart, InputIteratorEnd, OutputIterator );das problem ist das die Operationen "in order" ausgefuehrt werden muessen. D.h. das ganze laesst sich wesentlich effizienter umsetzen, wenn ich das Bild vorher selber aufteile und beim eigentlichen Algo ganz auf jeglich synchronisation versichten kann (das kann openMP dann besser
).in Image OP passiert im prinzip immer sowas (pseudocode)
while( InputIteratorStart != InputIteratorEnd ) { //some fanzy calculation stuff here.... *OutputIterator = result; ++OutputIterator; ++InputIteratorStart; }Hab eh vor das ganze auf CodeProject als Artikel reinzustellen, vlt. laest sich das besser diskutieren wenn man mal das Gesamtgebilde sieht... Ich finde halt das das Ziel sein sollte, das single - core user keinen penalty fuer die parallelisierung bezahlen sollten :).