Parallelisierung mit OpenMP / Dynamisch threads erzeugen
-
Stefan_O schrieb:
Blue-Tiger schrieb:
Hmm... die erste deiner 2 geposteten Versionen ist "falsch", da du bei jedem Aufruf von findfrequencies einen neuen "omp parallel"-Abschnitt hast. Und jeder "omp parallel"-Abschnitt startet dir X neue Threads.
Mehr Threads starten als festgelegt tut er nicht, aber es ist wie gesagt extrem langsam.
Na ja, es ist auch sehr,sehr langsam, da du durch die Verschachtelten "parallel"-sections den gleichen Code viel oefters ausfuehrst als du eigentlich willst: http://software.intel.com/en-us/articles/32-openmp-traps-for-c-developers/#IDANOQDC (allgemein sehr empfehlenswert, der Artikel).
Blue-Tiger schrieb:
Wozu? die Threads werden ja alle beim "omp parallel" gestartet und wartn dann alle auf neue Tasks (bis auf den einen Thread, der in die "single"-Section rein kommt). D. h. OpenMP macht das eh automatisch.
Natürlich um das programm schneller zu machen
So scheint es ja noch nicht optimal zu funktionieren. Desweiteren fehlt mir noch eine Lösung für windows. mingw will schon bei win32 OpenMP nicht (anscheinend funktionieren nur ältere versionen, da gibts aber noch kein OpenMP 3.0), und da x64 deutlich schneller brauch ich mingw-w64 mit openmp, dazu finde ich gar nichts. Das heißt ich brauch wohl eine Lösung die ohne tasks auskommt.Hmm... mit MinGW/Windows kann ich dir leider nicht helfen. Ich geh davon aus dass du beim TDragon-Release alles richtig gemacht hast (du musst sowohl -gomp als auch -lpthreads als Optionen mitgben). Find es allerdings sehr komisch dass das nicht geht (zumindest mit TDragon-gcc 4.2 (oder war es 4.3?) funktionierte OpenMP noch einwandfrei (Leider gibts erst ab 4.4 support fuer omp tasks). Funktionieren denn andere Minimal-OpenMP-Beispiele mit dem TDragon-gcc?
Auf sections wuerd ich nicht zurueckgreifen, die sind einfach nicht fuer das gemacht was du vorhast. Notfalls muesstest du wohl von Hand Threads programmieren; ist auch nicht sooooo schwer (und PThreads gibts sowohl fuer Linux als auch fuer Windows, und ich vermute auch fuer Macs).
Eine (von mir nicht getestete) Moeglichkeit waer noch, von Linux aus fuer Windows crosscompilen, geht bei neueren Distris relativ einfach (die haben oft irgendwelche mingw-packages), aber k.A. wie's da mit GOMP (GNU OpenMP)-support ausschaut. Noch extremer: du koenntest dir den MinGW selbst bauen (aber eigentlich sollte das TDragon-Release schon funktionieren).
-
Na ja, es ist auch sehr,sehr langsam, da du durch die Verschachtelten "parallel"-sections den gleichen Code viel oefters ausfuehrst als du eigentlich willst: http://software.intel.com/en-us/articles/32-openmp-traps-for-c-developers/#IDANOQDC (allgemein sehr empfehlenswert, der Artikel).
Ist es den möglich innerhalb einer section eine weitere zu haben? für den Fall könnte man das omp parallel ja rausziehen aus der funktion und innerhalb die sections haben.
Hmm... mit MinGW/Windows kann ich dir leider nicht helfen. Ich geh davon aus dass du beim TDragon-Release alles richtig gemacht hast (du musst sowohl -gomp als auch -lpthreads als Optionen mitgben). Find es allerdings sehr komisch dass das nicht geht (zumindest mit TDragon-gcc 4.2 (oder war es 4.3?) funktionierte OpenMP noch einwandfrei (Leider gibts erst ab 4.4 support fuer omp tasks). Funktionieren denn andere Minimal-OpenMP-Beispiele mit dem TDragon-gcc?
Nein, mit dem TDragon-gcc funktioniert nichts mit OpenMP. Ich habe gelesen das OpenMP nur bei älteren builds funktioniert hat. Und selbst wenn es gehen würde, ist es nicht 64-bit. Das problem scheint zu sein das libgomp zur Zeit nicht mit win32 threads funktioniert und libgomp->pthreads->win32 threads instabil ist. Das heißt cross-compiling hilft auch nicht.
Der Intel-Compiler kann OpenMP 3.0, ist aber für Windows nicht kostenlos, nur 30-tage demo. Und man muss ihn überlisten damit die erzeugten programme auch mit AMD prozessoren schnell sind.Auf sections wuerd ich nicht zurueckgreifen, die sind einfach nicht fuer das gemacht was du vorhast. Notfalls muesstest du wohl von Hand Threads programmieren; ist auch nicht sooooo schwer (und PThreads gibts sowohl fuer Linux als auch fuer Windows, und ich vermute auch fuer Macs).
Muss man da was komplett anderes machen oder kann man das einfach mit #ifdef und 3 zeilen code für jedes OS lösen? Geht das mit den critical sections so einfach oder muss ich da was kompliziertes bauen?
Auch wenns off-topic ist, aber ich bin zufällig als ich nach einem schnellen memcpy gesucht habe, darauf gestoßen, dass
if (a<0 || a>=b) continue;
für schnellere ausführung durch
if ((unsigned int)a >= (unsigned int)b) continue;
ersetzt werden sollte. da das ein paar mal vorkommt in den Funktionen die innerhalb der schleife aufgerufen werden, dacht ich mir, vielleicht bringt es ja einen messbaren vorteil ansonsten schadet es nicht:
Von 59 sekunden runter auf 39! ich dachte ich bin blöd, habe aber die zeilen wieder zurückgeändert, nochmal kompiliert, aber es liegt wirklich daran. wenn man mal nachzählt taucht das auch in jeder check-funktionen je nachdem wie viel er schon gerechnet hat zwischen 4 und 45 mal auf in meinem test.Vielen Dank
Stefan
-
Stefan_O schrieb:
Na ja, es ist auch sehr,sehr langsam, da du durch die Verschachtelten "parallel"-sections den gleichen Code viel oefters ausfuehrst als du eigentlich willst: http://software.intel.com/en-us/articles/32-openmp-traps-for-c-developers/#IDANOQDC (allgemein sehr empfehlenswert, der Artikel).
Ist es den möglich innerhalb einer section eine weitere zu haben? für den Fall könnte man das omp parallel ja rausziehen aus der funktion und innerhalb die sections haben.
Da bin ich ueberfragt, mit section kenn ich mich nicht naeher aus
Hmm... mit MinGW/Windows kann ich dir leider nicht helfen. Ich geh davon aus dass du beim TDragon-Release alles richtig gemacht hast (du musst sowohl -gomp als auch -lpthreads als Optionen mitgben). Find es allerdings sehr komisch dass das nicht geht (zumindest mit TDragon-gcc 4.2 (oder war es 4.3?) funktionierte OpenMP noch einwandfrei (Leider gibts erst ab 4.4 support fuer omp tasks). Funktionieren denn andere Minimal-OpenMP-Beispiele mit dem TDragon-gcc?
Nein, mit dem TDragon-gcc funktioniert nichts mit OpenMP. Ich habe gelesen das OpenMP nur bei älteren builds funktioniert hat. Und selbst wenn es gehen würde, ist es nicht 64-bit. Das problem scheint zu sein das libgomp zur Zeit nicht mit win32 threads funktioniert und libgomp->pthreads->win32 threads instabil ist. Das heißt cross-compiling hilft auch nicht.
Interessant, thx fuer die Info
(Hast du zufaellig Quellen oder Bugreports, damit man den Fortschritt mitverfolgen kann?
)
Auf sections wuerd ich nicht zurueckgreifen, die sind einfach nicht fuer das gemacht was du vorhast. Notfalls muesstest du wohl von Hand Threads programmieren; ist auch nicht sooooo schwer (und PThreads gibts sowohl fuer Linux als auch fuer Windows, und ich vermute auch fuer Macs).
Muss man da was komplett anderes machen oder kann man das einfach mit #ifdef und 3 zeilen code für jedes OS lösen? Geht das mit den critical sections so einfach oder muss ich da was kompliziertes bauen?
Na ja, normale multithreading-libraries unterscheiden sich grundlegend von OpenMP. Du musst wesentlich mehr selbst Hand anlegen, d.h. Threads von Hand erstellen, Daten auf Threads verteilen, etc. Rechne mal 1-2 Tage Lernaufwand, wenn du mit der grundlegenden Problematik vertraut bist.
Es gibt verschiedene Libs. Wenn du mit C arbeitest bietet sich pthreads an.
pthreads gibts dann sowohl fuer Windows, MacOS als auch fuer Linux. Du benoetigst daher also nichtmal ein #ifdef
(Pthreads fuer 64bit-Windows muss man sich anscheinend selbst kompilieren, aber es funktioniert laut http://old.nabble.com/pthreads-on-64bit-Windows-td27329918.html ).Auch wenns off-topic ist, aber ich bin zufällig als ich nach einem schnellen memcpy gesucht habe, darauf gestoßen, dass
if (a<0 || a>=b) continue;
für schnellere ausführung durch
if ((unsigned int)a >= (unsigned int)b) continue;
ersetzt werden sollte. da das ein paar mal vorkommt in den Funktionen die innerhalb der schleife aufgerufen werden, dacht ich mir, vielleicht bringt es ja einen messbaren vorteil ansonsten schadet es nicht:
Von 59 sekunden runter auf 39! ich dachte ich bin blöd, habe aber die zeilen wieder zurückgeändert, nochmal kompiliert, aber es liegt wirklich daran. wenn man mal nachzählt taucht das auch in jeder check-funktionen je nachdem wie viel er schon gerechnet hat zwischen 4 und 45 mal auf in meinem test.Na klar, ein unsigned kann auch nicht <0 sein, deswegen muss der Compiler das auch nicht ueberpruefen. Er laesst die Ueberpruefung also einfach weg.
Wenn a trotzdem <0 sein kann, wird dein Code allerdings nicht mehr richtig funktionieren. Wenn a nie kleiner als 0 sein kann, haettest du's sowieso am besten von vorn herein als unsigned deklariert. Das macht den Code eindeutiger (weil dann jeder sieht dass a>=0) und hilft wie du selbst gemerkt hast, dem Compiler beim optimieren.
Grundsaetzlich kannst du ausserdem davon ausgehen dass memcpy optimal implementiert ist. Wuerd mich wundern wenn du da was schnelleres hinkriegst als die Leute, die den Compiler/die Standardbibliothek geschrieben haben; ausser du hast sehr spezielle Anforderungen.
-
Blue-Tiger schrieb:
Na klar, ein unsigned kann auch nicht <0 sein, deswegen muss der Compiler das auch nicht ueberpruefen. Er laesst die Ueberpruefung also einfach weg.
Wenn a trotzdem <0 sein kann, wird dein Code allerdings nicht mehr richtig funktionieren.
Der Trick ist, dass die Zahlen kleiner als 0 als unsigned interpretiert groß sind und vorallem größer als der größte signed integer. Daher ist das eine Abkürzung. Wobei ich nicht weiß, was der Standard dazu sagt. Ob das im Grunde UB ist :).
Wundert mich eigentlich, dass der GCC das nicht selbst macht, weil der ähnliche Fälle optimieren kann.
-
rüdiger schrieb:
Blue-Tiger schrieb:
Na klar, ein unsigned kann auch nicht <0 sein, deswegen muss der Compiler das auch nicht ueberpruefen. Er laesst die Ueberpruefung also einfach weg.
Wenn a trotzdem <0 sein kann, wird dein Code allerdings nicht mehr richtig funktionieren.
Der Trick ist, dass die Zahlen kleiner als 0 als unsigned interpretiert groß sind und vorallem größer als der größte signed integer. Daher ist das eine Abkürzung. Wobei ich nicht weiß, was der Standard dazu sagt. Ob das im Grunde UB ist :).
Aber nur wenn b immer >=0 ist, oder missverstehe ich was?