Dakuan
Anmeldungsdatum: 2. November 2004
Beiträge: 6345
Wohnort: Hamburg
|
In den meisten Plattform übergreifenden Toolkits sind die Möglichkeiten eines Threads ja etwas eingeschränkt. So ist es normalerweise nicht möglich, das ein Thread in einer GUI irgendetwas an der Grafik Ausgabe direkt verändern darf/kann oder grafische Objekte erstellen kann. Andererseits finde ich immer wieder (CLI) Beispiele, in denen die erzeugten Threads per printf() oder cout Ausgaben erzeugen, was dann aber offenbar in einem anderen Kontext geschieht (da ein anderer Prozess). Ich finde aber keine Information darüber, ob ein Thread problemlos Datei i/o machen kann/darf. Falls das möglich ist, stellt sich noch die Frage, ob das in meinem speziellen Fall überhaupt sinnvoll ist. Da sollen mehrere Bilder eingelesen und skaliert werden, was ich nach Möglickeit in parallelen Threads erledigen möchte. Da würde sich dann natürlich auch die Frage stellen, inwieweit sich die Leseoperationen gegenseitig ausbremsen. Aber soweit ich bisher gesehen habe, werden die Bilddaten immer blockweise gelesen und dann blockweise dekodiert. Daraus erwächst die Hoffnung, das die Aufspaltung in mehrere Threads einen kleinen Zeitgewinn ergeben könnte. Ich bin da noch in der Planungsphase, daher würde mich interessieren, ob der Denkansatz überhaupt vielversprechend ist oder ob ich komplett daneben liege. Was denkt Ihr darüber?
|
Seebär
Anmeldungsdatum: 2. Mai 2009
Beiträge: 829
|
Dakuan schrieb: Ich finde aber keine Information darüber, ob ein Thread problemlos Datei i/o machen kann/darf.
Natürlich "darf" ein Thread das. Wieso nicht? Grundsätzliche Themen bei Multithreading sind Dinge wie starvation, deadlocks etc..
Ob (d)eine Parallelisierung etwas bringt hängt vom konkreten Anwendungsfall ab. Natürlich bekommt "die Platte" bei parallelem IO mehr Last, aber man wird ja im Regelfall nicht nur Files zum Spaß öffnen sondern auch etwas damit tun. Sprich: die Last ist dann nicht nur I/O-bound, sondern auch bzgl. CPU fällt Last an. Habe selbst einen konkreten Fall in dem ich über 50.000 Files parallel verarbeitet, mit 4 Cores dabei etwa Faktor 3 .. 3,5 heraushole. Die Hyper-Threaded-Cores (so vorhanden) solltest du bei solchen Rechnungen im Übrigen ausklammern / niedriger ansetzen.
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12829
|
Ja, Datei-IO geht parallel. Ob es sich lohnt, hängt in erster Linie von der Beantwortung einer einfachen Frage ab: ist die Verarbeitung auf Deinem System IO-bound oder CPU-bound? Falls IO-bound, dann lohnt es sich nicht zu parallelisieren, es sei denn, die Dateien liegen auf physikalisch unterschiedlichen Geräten, so dass die gesamte nutzbare IO-Bandbreite größer ist als die eines Gerätes. Du findest das am einfachsten heraus, indem Du den Diskcache leerst und die Umwandlung ein mal in einem Thread ausführst. Wenn eine CPU bei 100% ist, dann ist es höchstwahrscheinlich CPU-bound und Parallelisierung könnte sich lohnen. Ich könnte noch mehr dazu schreiben, aber mir fehlt die Zeit.
|
noisefloor
Ehemaliger
Anmeldungsdatum: 6. Juni 2006
Beiträge: 29064
Wohnort: WW
|
Hallo,
In den meisten Plattform übergreifenden Toolkits sind die Möglichkeiten eines Threads ja etwas eingeschränkt. So ist es normalerweise nicht möglich, das ein Thread in einer GUI irgendetwas an der Grafik Ausgabe direkt verändern darf/kann oder grafische Objekte erstellen kann.
Was aber IMHO daran liegt, dass bei GUI Toolkits der Mainloop der GUI die Kontrolle haben muss und man da nicht reinfummeln sollte. Qt hat aber z.B. eine eigene Thread-Klasse, die man in den Mainloop integrieren kann. Keine Ahnung, wie anderen GUI-Toolkits das handhaben / anbieten. Bei nebenläufige Programmieren gibt es kein pauschales Rezept, weil es auch auf die Programmiersprache bzw. deren Implenentierung(en) von nebenläufiger Programmierung ankommt. Z.B. kann bei CPython, der Python Referenzimplementierung, immer nur ein Thread gleichzeitig laufen, echt parallel geht nicht. Ist bei C/C++ aber AFAIK anders. Die wichtigsten Stichworte - CPU-bound und I/O-bound - wurden ja schon genannt. Bei I/O-bound Problemem ist hat die Schnittstelle zum I/O-Device in der Regel die Bremse, nicht die CPU. Gruß, noisefloor
|
Dakuan
(Themenstarter)
Anmeldungsdatum: 2. November 2004
Beiträge: 6345
Wohnort: Hamburg
|
Also der IO Anteil ist schon recht hoch. Wie hoch kann ich allerdings nicht genau sagen. Was mein Programm anschließend macht verbraucht dann nochmal etwa 20% der Zeit. Das sind dann Größenordnungen zwischen 15 und 170 ms. Bei längeren Aktionen höre ich wie der Lüfter lauter wird. Das tut er sicherlich nicht wenn die CPU sich langweilt. Ich habe mir auch mal angesehen, wie mein Toolkit Bilddateien einließt. Da wird immer ein Block gelesen und dann an den und dann an den Decoder (libjpg) weitergereicht. Ob man die Pause nutzen kann, weiß ich nicht. Bisher habe ich nur 2 Mal mit einem zusätzlichen Thread gearbeitet und das auch nur um zwei Vorgänge voneinander zu entkoppeln. rklm schrieb: Ich könnte noch mehr dazu schreiben, aber mir fehlt die Zeit.
Schade eigentlich. Aber nach allem, was ich bisher im Netz gelesen habe, ist das tatsächlich ein recht umfangreiches Thema. Daher habe ich mir gestern ein Buch darüber bestellt (C++ Concurrency) was aber erst Mitte der Woche da ist.
|
Dakuan
(Themenstarter)
Anmeldungsdatum: 2. November 2004
Beiträge: 6345
Wohnort: Hamburg
|
@noisefloor Ich habe wieder zu lange an meiner Antwort gebastelt und daher Deinen Post nicht gesehen. Also ich verwende FLTK. das hält sich da komplett raus. Ich kann also pthreads nehmen (gibt entsprechende Beispiele, wie man das in C++ einbindet, wird immer mit Java verglichen) oder das was die neueren C++ Versionen mitbringen. Auch wenn das wenig bringen sollte, ist das sicherlich sehr lehrreich.
|
Seebär
Anmeldungsdatum: 2. Mai 2009
Beiträge: 829
|
Dakuan schrieb: Also der IO Anteil ist schon recht hoch. Wie hoch kann ich allerdings nicht genau sagen.
Eine einfacher Versuch das zu prüfen ist Dann siehste sekündlich die Verteilung der Threads, die Summe aus us+sy ist deine CPU-Last, unter wa sollte u.a. der IO sein. (Natürlich kannst Du noch parallel iotop nehmen, falls das was bringt)
Was mein Programm anschließend macht verbraucht dann nochmal etwa 20% der Zeit. Das sind dann Größenordnungen zwischen 15 und 170 ms.
Wie meinen? Die 20% reichen von 15 Sekunden (da fehlt die Einheit) bis nur 170ms, oder bezieht sich das auf alles? Egal wie: kalkuliere vorher ob sich das überhaupt lohnt! Wenn du nur wenige Sekunden hast und es Wurst ist ob es nun 10s oder 3s dauert, dann Finger weg. Mal vom Lerneffekt abgesehen. Wenn du selbst den Prozess immer wieder anwendest und aus einer Minute dann 10s machst, ja dann natürlich 😉 (als Entwickler darf man sich ruhig selbst der Nächste ein...) Noch genauer: je nach Programmiersprache ist Multithreading durchaus teuer. Bestes Bsp. dafür ist Java. Auf Micro-Ebene zu parallelisieren führt dort zum Effekt, das die Last hochgeht und die Dauer zunimmt, da der Overhead im Vergleich zur unit-of-work viel zu teuer ist. Das vermute ich aber bei deiner Sache eher nicht, außerdem weiß ich nicht C++ da tickt.
|
Dakuan
(Themenstarter)
Anmeldungsdatum: 2. November 2004
Beiträge: 6345
Wohnort: Hamburg
|
Momentan läuft noch alles sequentiell ab. Aber ich habe top trotzdem mal gestartet:
Tasks: 232 total, 2 running, 166 sleeping, 0 stopped, 0 zombie
%Cpu(s): 12.7 us, 0.2 sy, 0.0 ni, 87.0 id, 0.0 wa, 0.0 hi, 0.1 si, 0.0 st
KiB Mem : 16382780 total, 13440524 free, 1096228 used, 1846028 buff/cache
KiB Swap: 18335740 total, 18335740 free, 0 used. 14898696 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
2431 manfred 20 0 103496 43348 8976 R 99.0 0.3 0:16.50 tview
Wahrscheinlich muss ich das nochmal direkt nach einem Neustart machen oder irgendwie einen Teil des Speichers 'abschalten'.
Wie meinen? Die 20% reichen von 15 Sekunden (da fehlt die Einheit)...
Wenn die Einheiten unterschiedlich wären, hätte ich das auch angegeben. Jedenfalls war damit die Schwankungsbreite gemeint. Die Bilder sind ja nicht alle gleich groß.
Egal wie: kalkuliere vorher ob sich das überhaupt lohnt! Wenn du nur wenige Sekunden hast und es Wurst ist ob es nun 10s oder 3s dauert, dann Finger weg.
Wahrscheinlich lohnt sich das eher nicht. Aber das kann in der Summe auch schon mal in den Minutenbereich gehen. Und mindestens einen zusätzlichen Thread werde ich wohl einbauen müssen, damit beim öffnen des Programm Menüs das eigentliche Programm weiter läuft.
Noch genauer: je nach Programmiersprache ist Multithreading durchaus teuer. Bestes Bsp. dafür ist Java.
Das ist bekannt. Deshalb will ich mal mit Thread pools experimentieren. Interessant ist, das ich zu diesem Thema viele Java Beispiele gefunden habe. C++ Beispiele sind da etwas seltener. Interessant ist dieses Beispiel. Aber um das zu verstehen, muss ich noch einiges an Hausaufgaben erledigen. Bei meiner Frage ging es hauptsächlich darum, wo das Datei I/O hin gepackt werden kann.
|
Neral
Anmeldungsdatum: 3. Oktober 2007
Beiträge: 229
|
@Dakuan: Wenn du ein fertiges Programm mehrfach aufrufen möchtest, ist vielleicht auch GNU parallel einen Blick wert. Damit spart man sich das nervige und fehleranfällige Threadprogrammieren, bezahlt aber mit der Startup-Zeit der Programme.
|
noisefloor
Ehemaliger
Anmeldungsdatum: 6. Juni 2006
Beiträge: 29064
Wohnort: WW
|
Hallo, @Neral: darum geht es nicht. Es geht darum, in einem selbst geschriebenen Programm mit FLTK-basierter GUI I/O Operationen nebenläufig zu gestalten. Gruß, noisefloor
|
Seebär
Anmeldungsdatum: 2. Mai 2009
Beiträge: 829
|
@Neral Danke für den Tipp, kann ich vmtl. gebrauchen. @noisefloor
Warum sollte es nicht darum gehen? Wenn es das Problem (besser) löst, dann ist es die Lösung. Direkt n Prozesse auf OS-Ebene statt das durch eine Durchlauferhitzerschicht samt Threading ist m.E. meist überlegen bzgl. Laufzeit. Die Steuerung der externen Prozesse wird da eher das Problem. Wenn er das aber einfach trennen kann, dann ist es das, auch wenn er es anders machen wollte. @Dakuan: jo, Thread-Pooling macht Java auch, wenn man es richtig einsetzt. Bleibt dennoch relativ "teuer".
|
Dakuan
(Themenstarter)
Anmeldungsdatum: 2. November 2004
Beiträge: 6345
Wohnort: Hamburg
|
Für mich kommt der Tipp leider zu spät.
Direkt n Prozesse auf OS-Ebene statt das durch eine Durchlauferhitzerschicht samt Threading ist m.E. meist überlegen bzgl. Laufzeit. Die Steuerung der externen Prozesse wird da eher das Problem.
So etwas hatte ich auch schonmal gemacht, allerdings auch vom eigenen Programm gestartet. Quasi so etwas wie ein "Plugin Ersatz". Die Steuerung der externen Prozesse wird da eher das Problem.
Dazu hatte ich eine bidirektionale Pipe eingerichtet. Aber ob das bei mehr als einem Prozess noch effektiv ist - da habe ich einige Zweifel. In meinem Fall geht es nicht nur darum, die Arbeit zu verteilen, sondern auch darum, die gefundenen Ergebnisse richtig zuzuordnen. Das ist in dem Wikipedia Artikel schön dargestellt, konnte ich so aber in der Beispiellösung so noch nicht finden.
|
noisefloor
Ehemaliger
Anmeldungsdatum: 6. Juni 2006
Beiträge: 29064
Wohnort: WW
|
Hallo,
Warum sollte es nicht darum gehen? Wenn es das Problem (besser) löst, dann ist es die Lösung.
Weil die Bilder in der GUI benötigt werden und die GUI möchte man nur 1x starten. Klar kann man unabhängig von der GUI X Service Worker starten, die vor sich hin ideln und darauf warten, I/O für die GUI machen zu dürfen. Halt ich ich hier aber für wenig zielführend und sinnvoll. Gruß, noisefloor
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12829
|
noisefloor schrieb: Bei I/O-bound Problemem ist hat die Schnittstelle zum I/O-Device in der Regel die Bremse, nicht die CPU.
Es kann auch das Gerät sein (rotierende Platten sind immer langsamer als jeder Bus, der in einem Rechner verbaut ist). Seebär schrieb:
@Dakuan: jo, Thread-Pooling macht Java auch, wenn man es richtig einsetzt. Bleibt dennoch relativ "teuer".
Ich weiß nicht, was Du genau meinst, aber einige Anwendungen des Hochfrequenzhandels sind in Java realisiert. Ich würde diese pauschale Aussage, dass Thread-Pooling in Java teuer ist bestreiten. Aber hier geht es ja nicht um Java. Die Probleme liegen oft eher in der richtigen Behandlung von Synchronisierung. Zur Datenerhebung: man kann auch ps dafür verwenden, wenn man einen Prozess gezielt beobachten will: | while ps --no-headers -o %cpu 12345 && sleep 1; do :; done
|
Dakuan schrieb: Also der IO Anteil ist schon recht hoch. Wie hoch kann ich allerdings nicht genau sagen. Was mein Programm anschließend macht verbraucht dann nochmal etwa 20% der Zeit. Das sind dann Größenordnungen zwischen 15 und 170 ms.
Anteil ist eigentlich nicht so interessant. Interessant ist, ob der Durchsatz des IO-Systems der Begrenzer ist oder die CPU.
Ob man die Pause nutzen kann, weiß ich nicht.
Das macht dann schon der Scheduler des Betriebssystems, wenn Du mit mehreren Threads oder Prozessen arbeitest.
rklm schrieb: Ich könnte noch mehr dazu schreiben, aber mir fehlt die Zeit.
Schade eigentlich.
Naja, die Kollegen sind ja schon eingesprungen. ☺
Aber nach allem, was ich bisher im Netz gelesen habe, ist das tatsächlich ein recht umfangreiches Thema. Daher habe ich mir gestern ein Buch darüber bestellt (C++ Concurrency) was aber erst Mitte der Woche da ist.
Naja, ermittle doch erst mal, wie die Konvertierung einer Datei sich verhält (%CPU und IO). Wenn das IO-bound ist, dann eher nicht parallelisieren.
|
Dakuan
(Themenstarter)
Anmeldungsdatum: 2. November 2004
Beiträge: 6345
Wohnort: Hamburg
|
Momentan tendiere ich dazu, das I/O vom Pool-Boss machen zu lassen und erstmal nur die Nachbehandlung in den Pool zu geben. Damit könnte ich dann aber nur den ca. 20% Zeitanteil etwas reduzieren.
Es kann auch das Gerät sein (rotierende Platten sind immer langsamer als jeder Bus, der in einem Rechner verbaut ist).
Dazu hatte ich bisher nichts gesagt, aber es klang vielleicht schon etwas durch. Tatsächlich habe ich bei diversen anderen Projekten schon beobachtet, das viele Verbesserungen bei USB-Platten keine Auswirkungen haben. Andererseits hat dieser PC zu viel Arbeitsspeicher. Viele Testergebnisse werden verfälscht, weil ein großer Teil der Dateien noch im Speicher liegt, und daher nicht immer echtes I/O statt findet.
Naja, ermittle doch erst mal, wie die Konvertierung einer Datei sich verhält (%CPU und IO). Wenn das IO-bound ist, dann eher nicht parallelisieren.
Ich habe keine Ahnung, wie ich das machen soll, bzw. was hier mit "Konvertierung" gemeint ist. Meine bisherigen Zeitangaben beruhen einmal auf dem Mittelwert "für alles" aus der Gesamtlaufzeit für ca. 400 Dateien und andererseits auf den gemessenen Zeiten für die verschiedenen Nachbehandlungen. Diese wurden bei bereits geladenen Dateien ermittelt, also ohne I/O Anteil.
... dann eher nicht parallelisieren.
Aber irgendwie muss ich doch mal lernen, die andere 6 Kerne zu beschäftigen ...
Die Probleme liegen oft eher in der richtigen Behandlung von Synchronisierung.
Ich denke, das beschränkt sich auf den Zugriff der Input- und Output-Queue. Ansonsten sehe ich da keine weiteren Berührungspunkte. Aber aus meinen beiden früheren Projekten weiß ich, das man da auch viele (Denk-) Fehler machen kann. Jedenfalls hoffe ich, das mein Buchhändler mir morgen nicht sagt, das das bestellte Buch doch nicht kommt. Ich werde dann meine Hausaufgaben machen und mal sehen wie weit ich komme. @noisefloor Klar kann man unabhängig von der GUI X Service Worker starten, die vor sich hin ideln und darauf warten, I/O für die GUI machen zu dürfen.
Ob die Worker das I/O machen, ist ja noch nicht entschieden. Nach dem bisher gesagten könnte das ja auch der Boss machen, der allerdings auch ein eigener Thread sein könnte. Damit wäre die Erfassung zumindest von der GUI entkoppelt, und würden nicht jedes Mal stehen bleiben, wenn ein Menü aufgerufen wird.
|