QThread statt OpenMP?

Alles rund um die Programmierung mit Qt
odenter
Beiträge: 36
Registriert: 5. Dezember 2009 10:02

Beitrag von odenter »

Wieso zwei Prozesse?

Du hast ein Prozess mit einem Thread (GUI). Aus diesem Thread heraus wird eine Berechnung (Deine Schleifen), vermutlich durch eine Aktion, getartet --> zweiter, neuer Thread.

Du hast also nun Deinen GUI-Thread und einen weiteren Thread der die Berechnung ausführt, die ja seriell abgearbeitet werden sollen!

Wenn der 2. Thread durch ist, meldet der an den Main-Thread arbeit erledigt. Und die GUI zeigt das an, total unkritisch.
Viel Kommunikation braucht man da nicht, maximal ne Statusinfo vom Arbeitsthread an den GUI-Thread. Und ggf. ein Abort vom GUI-Thread an den Arbeitsthread.

Interessant wäre, was und wie da berechnet wird, vermutlich kann da noch ordentlich getuned werden, aber das war ja nicht die Frage.
Sollte es nach dem auslagern in einen Arbeitsthread trotzdem noch sehr, sehr lange dauern, Profiler und gucken was da die Zeit frisst.
m.mickey
Beiträge: 27
Registriert: 10. Januar 2010 23:01

Beitrag von m.mickey »

odenter hat geschrieben:Wieso zwei Prozesse?

Du hast ein Prozess mit einem Thread (GUI). Aus diesem Thread heraus wird eine Berechnung (Deine Schleifen), vermutlich durch eine Aktion, getartet --> zweiter, neuer Thread.
Weil in dem zweiten Thread OpenMP parallelisierte Schleifen laufen sollen und das funktioniert nicht zusammen. Es kompiliert, aber dann bekomm ich nen libgomp1.dll error...

Wenn ich ohne -fopenmp kompilier, startet er mir die anderen Threads und alles läuft super, nur eben innerhalb der Threads nicht parallel (was ich ja grad brauche ;-) )...

Naja es ist ne Bildbearbeitung hat also viele verschiedene Schleifen über die einzelnen Pixel, wobei einige Filter nicht kachelbar sind, sodass man es effektiv ini QThread bauen könnte...

Viele Grüße mickey
m.mickey
Beiträge: 27
Registriert: 10. Januar 2010 23:01

Beitrag von m.mickey »

Ok, ein paar Tests später...

Ich kann im Hauptthread Schleifen mit OpenMP parallelisieren und nebenbei "normale" QThreads laufen lassen. Es funktioniert nicht, wenn ich versuche Schleifen in einem Nebenthread mit OpenMP zu parallelisieren...
Dumm ist nur, dass die GUI im Hauptthread laufen muss, gibts dafür einen Workaround, also die GUI in einen parallelen Thread, der schon zu Anwendungsbeginn gestartet wird?

Viele Grüße mickey
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag von RHBaum »

Das schraenkt die verwendbarkeit von openMP IMHO schon extrem ein. Nicht nur im Hinblick auf die QT.

Sicher das es bei openMP da keine Kniffe gibt ?
wie komplex ist das deine angestrebte Optimierung ? Vielleicht iss ne Loesung ohne Openmp mit klassischer threadverwaltung ne Option ?
Wie komplex ist dein Datenaustausch/Eventhaendling ? Vielleicht iss doch extprozess mit ner einfachen IPC (Pipe ? ) ne möglichkeit.

Und fuer die QT iss mir nix bekannt, ich vermut das ohne tiefgreifende eingriffe und umschreiben der QT da gar nix geht. Windows macht intern vieles ueber Prozess und threadhandles in hinblick auf Ressourcen/Speicherverwaltung. Und QT verwendet sicher ne menge davon.

Ciao ...
m.mickey
Beiträge: 27
Registriert: 10. Januar 2010 23:01

Beitrag von m.mickey »

RHBaum hat geschrieben:Das schraenkt die verwendbarkeit von openMP IMHO schon extrem ein. Nicht nur im Hinblick auf die QT.

Sicher das es bei openMP da keine Kniffe gibt ?
wie komplex ist das deine angestrebte Optimierung ? Vielleicht iss ne Loesung ohne Openmp mit klassischer threadverwaltung ne Option ?
Wie komplex ist dein Datenaustausch/Eventhaendling ? Vielleicht iss doch extprozess mit ner einfachen IPC (Pipe ? ) ne möglichkeit.

Und fuer die QT iss mir nix bekannt, ich vermut das ohne tiefgreifende eingriffe und umschreiben der QT da gar nix geht. Windows macht intern vieles ueber Prozess und threadhandles in hinblick auf Ressourcen/Speicherverwaltung. Und QT verwendet sicher ne menge davon.

Ciao ...
Naja es scheint ein Fehler in der Implementierung von OpenMP zu sein, aber ich kann den nicht beheben und Bug Reports dazu gibts schon, ich such eben grad nen Workaround...
Also der Datenaustausch wären mehrere Zeiger auf Datenfelder (Bilder) und eine Qt Settingsklasse. Die verschiedenen Filter sind mit OpenMP parallelisiert, aber eben nur einige Schleifen der Filter, weil sich manche Abschnitte nicht parallelisieren lassen... also im wesentlichen immer wieder verschiedene for-Schleifen, deren Durchgänge durch die Anzahl der Prozessoren geteilt wird, was bei Quadcore oder mehr schon nen recht deutlichen Zugewinn ausmacht... Und da es in der Summe doch einige sind, sollte es sich natürlich recht einfach implementieren lassen, "pragma omp parallel for" is halt einfach hinzuschreiben... Oder ne Idee wie ich solche Schleifen effektiv mit QThread parallelisieren könnte?
Also wenn ich recht verstehe, ist es mit QT unmöglich die EventQueue der GUI in einen anderen als den Hauptthread zu verlegen?
Für mich scheint die zwei Prozess Lösung immer wahrscheinlicher, auch wenn es wohl ne Menge Arbeit wäre (und ich noch keinen Plan hab, wie das überhaupt geht).
Vielen Dank für eure Hilfe.
Viele Grüße mickey
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag von RHBaum »

Also wenn ich recht verstehe, ist es mit QT unmöglich die EventQueue der GUI in einen anderen als den Hauptthread zu verlegen?
Kannst ja mal ne Mail an die trolltechler schreiben, aber ich glaubd as kaem auf ne neuimplementation raus.

Wie umfangreich iss deine GUI, und wie bereit bist dich selbst zu geiseln ^^ Win32 hat die einscharaenkung mit den threads nicht ganz so (also es gibt da auch einschraenkungen), aber da koenntest bissi mehr machen.


Für mich scheint die zwei Prozess Lösung immer wahrscheinlicher, auch wenn es wohl ne Menge Arbeit wäre (und ich noch keinen Plan hab, wie das überhaupt geht).
2 Prozesse und Zeiger, das beisst sich !!! über prozessgrenzen kannst zeiger vergessen !
Du kannst also immer nur die kompletten daten ueber eine IPC zwischen den prozessen austauschen.

Als IPC gibt es shared Memory, Pipes, Netzwerkstack, oder eben filesystem direkt.

Ob es kompliziert sein muss, keine ahnung, man kann es sicher richtig komliziert machen bei solchen themen.

Wenn ich richtig verstehe, hasst du ein Datenfeld, und eine Art konfiguration (Filter), damit manipulierst Du die dieses Datenfeld. Wenn du da keine weiteren eingriffe / events hasst, waer das sogar eher einfach.

dein hauptprogramm schreibt das datenfeld auf die platte (temp file) dazu die einstellungen in ein entsprechendes Konfig file, und ruft dann ein hilfsprogramm fuer auf mit den files als parameter auf, ausm seperaten thread der auch gleich auf den exit status des hilfsprogramms wartet, und voiala, du hasst multiprozessing (2 nicht verwande prozesse) in ner recht einfachen form.
Sowas waer recht einfach im hauptprogramm mit der qt zu realisieren.
und das hilfsprogramm als konsolenanwendung mit openMP sicher auch ned zu kompliziert, wenn man sich scho mit openMP auskennt.

wenn das funktioniert, kannst das immer noch aufbohren.
Man findet die temp files doof ? -> ersetzen durch (named) shared memory
man will den Fortschritt sehen ? -> dein hiflsprogg printet fleissig auf stdout, das hauptprogramm parst das und baut ne progressanzeige drumrum.

Ciao ....
m.mickey
Beiträge: 27
Registriert: 10. Januar 2010 23:01

Beitrag von m.mickey »

Danke für deine Erläuterungen.

Ja, es sind mehrere Datenfelder (Zwischenschritte) und die Settings für die Filter, sonst nur ein Statusupdate... Also sollte in deinen Maßstäben unter einfach fallen.
Da es recht schnell in den Bereich von 1 GB geht wird shared memory wohl die beste Lösung sein.
Hast du vielleicht noch nen Link für mich, mit nem entsprechenden Beispiel in QT?
Wirklich schade, dass dieser Fehler mit OpenMP existiert, es wär alles so einfach gewesen ;-)

Viele Grüße mickey
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag von RHBaum »

Da es recht schnell in den Bereich von 1 GB geht wird Shared Memory wohl die beste Lösung sein.
Nein, eher nicht.
Bei groessen ueber 100 MiB und mehr denk ich prinzipiell eh schon über Tempfiles nach.
Bedenke: nen 32bit System kann ohne erweitertes Adressmodell(langsam) grad mal 4 GiB verwalten.
Windows 32 hat ne interne bescharaenkung für prozesse. Nen Prozess unter windows 32 wird ohne bestimmte massnahmen nie mehr wie 2 GiB Speicher adressieren koennen. (weiss ned wie es bei den "Servern" laeuft) und bei den 2Gib muss dann alles bei sein, also stack, heap, const Dataen ... etc.
Ich krieg auf einigen Rechnern bei uns (speicherausbau 2Gib) schon probleme die 1000 MiB allokieren zu wollen.

Dir bleiben also ned viel Reserven
Hast du vielleicht noch nen Link für mich, mit nem entsprechenden Beispiel in QT?
Warum willst Du immer Beispiele mit QT ....
Das schoene an der QT ist, das es mit dem rest der C++ und damit auch der C Welt harmoniert :-)
Als SW Entwickler sollt man eh darin geeicht sein, seine Probleme zu "modularisieren" also schoen in teilprobleme Aufzuloesen. Zumindest die Oberflaeche und die Logic sollten voneinander (fast) unabhaengig sein, das hat sich bisher immer bewaehrt.
Die Teilprobleme kann man wiederum kann man mit vielen möglichkeiten realisieren.

Ich find, die QT iss nen super framework fuer GUIs. Sobald ich aber libs schreibe, die nix mit der Oberflaeche zu tun hat, werd ich die QT meiden wie die Pest (Abhaengigkeit, undurchsichtiges datasharing). Da gibt es bessere Frameworks (vielleicht nicht ganz so komfortable, dafuer aber mit Anderen vorteilen).

In der Doku zur QT iss nen besipiel fuer shared memory auch drin ... besser kann mans ned erklaeren.

Ich wuerd mir aber lieber die grundlagen zu deinen BS anschauen, im Falle von windows ist es CreateFileMapping die zentrale API funktion. Und das prinzipielle verstehen. Da weiss ich ned wie der vorkenntnisstand ist.
Das ganze iss vom erforderlichen wissen her ziemlich komplex.

Danach wuerd ich schauen, was es fuer bibs gibt, die dir da unterstuetzung bieten. Wenn du Multiprozessing und IPC und shared memory prinzipiell verstanden hasst, isss das QT beispiel eigentlich nur noch ne darstellung der QT funktionen fuer Shm. das beispiel iss so simpel dann .... und die SHM in qt verwenden auch ^^

Les Dich in das Thema ein ....
Und parralel entwickel erst mal nen programm (ohne oberflaeche), was dir genau das tut was du willst, und seine Daten aus dateien holt. mit OpenMP.
Den code wirst immer weiterverwenden koennen spaeter ...
Ob das mit SHM, pipes oder dann doch inprozess loesst, kannst entscheiden wenn tiefer in der materie steckst.

Ciao ...
m.mickey
Beiträge: 27
Registriert: 10. Januar 2010 23:01

Beitrag von m.mickey »

RHBaum hat geschrieben: Warum willst Du immer Beispiele mit QT ....
Weil ich noch nicht sooo lange programmiere und viele Dinge einfach noch nicht kann. Zusätzlich hab ich QT als eine sehr umfassende Bibliothek kennengelernt mit der so manches einfacher geht...

Es scheint als wäre der Bug von OpenMP nun doch endlich behoben, ein patch steht bereit, aber ich hab ihn noch nicht getestet. Damit wäre es dann endlich möglich in nem QThread ne Schleife mit OpenMP zu parallelisieren und ich hätte keine Probleme mehr. Falls nicht sehe ich den Umweg über eine Trennung des Programms als sinnvollste Lösung, vielen Dank für die netten Hinweise dazu.

Also vielen Dank für eure Hilfe.

Viele Grüße mickey
pfid
Beiträge: 535
Registriert: 22. Februar 2008 16:59

Beitrag von pfid »

Ich hab das hier nur beiläufig mitgelesen, daher die Frage: Was spricht jetzt eigentlich dagegen, deine Berechnung in einem QThread (mit oder ohne Pool) oder QtConcurrent laufen zu lassen?
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag von RHBaum »

Was spricht jetzt eigentlich dagegen, deine Berechnung in einem QThread (mit oder ohne Pool) oder QtConcurrent laufen zu lassen?
OpenMP macht ne Menge impliziet. z.b. ne triviale for schleife kann OpenMP auf mehrere threads aufsplitten.
Mit klassischer threadprogrammierung musst du die schleife selber aufsplitten. was an der Stelle zu deutlich mehr (verwaltungs)Code führt. Und wahrscheinlich iss openMP auch noch effektiver weil es nicht eine Abstraktionsnsschicht zwischen hat wie die QT(plattformunabhaengigkeit) sondern direkt vom compiler interpretiert und ins assambly überfuehrt wird.

Wenn er wirklich performance braucht, und die funktionalitaet wirklich in den Schleifen haengt, würd ich definitiv auch OpenMP in erwaegung ziehen und auf die Plattformunabhaengigkeit etc pfeiffen (an der Stelle). Ob das bei Ihm der Fall iss, kann er nur selber beantworten.

Ciao ...
odenter
Beiträge: 36
Registriert: 5. Dezember 2009 10:02

Beitrag von odenter »

RHBaum hat geschrieben:
Was spricht jetzt eigentlich dagegen, deine Berechnung in einem QThread (mit oder ohne Pool) oder QtConcurrent laufen zu lassen?
Wenn er wirklich performance braucht, und die funktionalitaet wirklich in den Schleifen haengt, würd ich definitiv auch OpenMP in erwaegung ziehen und auf die Plattformunabhaengigkeit etc pfeiffen (an der Stelle). Ob das bei Ihm der Fall iss, kann er nur selber beantworten.
Ciao ...
Es geht ja auch nur eins, entweder Performance, oder Portabilität.
m.mickey
Beiträge: 27
Registriert: 10. Januar 2010 23:01

Beitrag von m.mickey »

RHBaum hat geschrieben: Wenn er wirklich performance braucht, und die funktionalitaet wirklich in den Schleifen haengt, würd ich definitiv auch OpenMP in erwaegung ziehen und auf die Plattformunabhaengigkeit etc pfeiffen (an der Stelle). Ob das bei Ihm der Fall iss, kann er nur selber beantworten.

Ciao ...
So wie ich das Problem einschätze ist das hier der Fall. Ob ein wirklich erfahrender Programmierer das genauso sieht weiß ich hingegen nicht.

Es muss ja nicht die performanteste Lösung sein, aber OpenMP bringt in langen Schleifen auf nem Quadcore schon nen deutlichen Performance Sprung ;-)

viele Grüße mickey
Antworten