Multithreading



  • ok, vielen vielen dank pub00515 !
    ich habe schon einiges gelesen, wäre dabei aber nie auf die idee gekommen, das was du geschrieben hast daraus zu interpretieren (wusste aber auch nicht wie ich es überhaupt interpretieren soll).
    also jetzt habe ich es endlich einmal verstanden. die anwendung ist dann eine andere sache, aber wenn ich mich jetzt mithilfe von ein paar tutorials einarbeite, werde cih das schon hinbekommen.

    also nochmals vielen dank!!

    mfg,
    julian



  • rüdiger schrieb:

    Message basiertes Threading ist deutlich leichter, aber leider weniger populär.

    weniger polulär?
    z.b. der windows fenstermanager benutzt message based threading...
    vor allen geht das auch ohne taskswitching (im sinne von cpu register und stackpointer umschalten).



  • pub00515 schrieb:

    Mutex ist ein Prozessübergreifendes Objekt (heißt also, man kann aus verschiedenen Programmen darauf zugreifen) und dient zur Synchronisation. Ein Mutex hat aber nur 2 zustandsgrößen - entweder Signaled oder Non-Signaled.

    Nee. Mutex ist ein binaerer Semaphor. Nichts weiter.

    pub00515 schrieb:

    Dann gibt es noch Critical Sections. Diese sind nur Thread übergreifend (also nicht Prozessübergreifend) und verhalten sich wie Mutexe. Nur verbraucht das setzen eines Critical Sections weniger CPU Cycles als bei Mutexen.

    WTF? Critical section ist der Grund, warum das ganze ueberhaupt ein Problem ist. Wie der Name schon sagt, ist es ein kritischer Abschnitt. Kritischer Abschnitt des Programms, welches der Prozess ausfuehrt.

    pub00515 schrieb:

    Atomare Typen sind Datentypen, dessen Änderung (also Schreiben) in einem einzigen CPU Cycle erfolgt. Unter 32 Bit Systemen (bei Windows) wären das 32 bit Integers. (bei char, short, float etc... wird das nicht garantiert). Bei einem Double braucht man unter Umständen mehrere Cycles. Was hat das mit Threads zu tun? Angenommen man hat 2 Threads, der eine schreibt dauernd einen Wert und der andere liest diesen aus. Wenn man mit atomaren Typen arbeitet, muss man theoretisch keine Synchronisation ausüben und der lesende Thread wird nie "Datenmüll" lesen (aber wird auch nicht mit dem schreibenden Thread synchron laufen). Ob das elegant ist, ist natürlich eine andere Frage.

    Atomar bedeutet unteilbar. Im Zusammenhang mit MT habe ich noch nie jemanden von atomaren Typen sprechen hoeren. Nur von atomaren Operationen.

    pub00515 schrieb:

    Analog dazu sind atomare Operationen Operationen, die in einem CPU Cycle erledigt werden. Somit ist das Lesen ODER das Schreiben eines normalen ints eine atomare Aktion. Übrrigens:

    ++i;
    

    ist nicht mehr atomar, da es das Lesen des Wertes und das Schreiben des Wertes erfordert.

    Auch nicht. Wie bereits geschrieben, heisst atomar unteilbar. In diesem Zusammenhang also nicht unterbrechbar. Und AFAIK ist ++i atomar, i++ ist es nicht.



  • Apollon schrieb:

    pub00515 schrieb:

    Mutex ist ein Prozessübergreifendes Objekt (heißt also, man kann aus verschiedenen Programmen darauf zugreifen) und dient zur Synchronisation. Ein Mutex hat aber nur 2 zustandsgrößen - entweder Signaled oder Non-Signaled.

    Nee. Mutex ist ein binaerer Semaphor. Nichts weiter.

    pub00515 schrieb:

    Dann gibt es noch Critical Sections. Diese sind nur Thread übergreifend (also nicht Prozessübergreifend) und verhalten sich wie Mutexe. Nur verbraucht das setzen eines Critical Sections weniger CPU Cycles als bei Mutexen.

    WTF? Critical section ist der Grund, warum das ganze ueberhaupt ein Problem ist. Wie der Name schon sagt, ist es ein kritischer Abschnitt. Kritischer Abschnitt des Programms, welches der Prozess ausfuehrt.

    pub0515 sieht das ganze vom standpunkt eines win32-coders.
    Apollon hält sich mehr an die allgemeine sichtweise.
    also habt ihr beide recht 😉



  • pub00515 schrieb:

    Eine Performancesteigerung erreichst du nur, wenn du mehrere Prozessoren oder Kerne hast. Bei nur einem Kern dürftest du sogar ein bisschen weniger "Umsatz" erzielen, da Windows (?) ständig hin und her schalten muss (zwischen den Threads).

    Laut Bruce Eckel (Autor von Thinking in C++ & Thinking in Java) bringt Multithreading praktisch häufig auch auf 1-Prozessor-Systemen leicht bessere Performance.

    Keine Ahnung obs stimmt, aber der Typ sollte eigentlich wissen, wovon er spricht. 🤡



  • byto schrieb:

    Laut Bruce Eckel (Autor von Thinking in C++ & Thinking in Java) bringt Multithreading praktisch häufig auch auf 1-Prozessor-Systemen leicht bessere Performance.

    ich würde eher sagen leicht schlechtere.
    das task switching selber verbrät ja auch rechenleistung.
    beste performance hat man, wenn die cpu ungehindert rennen kann, ohne interrupts usw...
    🙂



  • Kommt halt auf die Operationen an und wie diese die CPU auslasten. Wenn Du lediglich Berechnungen durchführst, ohne dass die Operation irgendwann blockt (z.B. durch I/O etc.), dann hast Du natürlich keine Performance-Steigerung. Aber sobald die Operation blockt, kannst Du eben Leistung steigern, indem die Kontrolle dann an einen zweiten Thread geht, um somit die CPU besser auszulasten.



  • Nochmal zu Atomaren Operationen. Da gibts in der Windows API die sogenannten Interlocked..... Funktionen mit denen kann man Inkrement/Dekrement/Addieren.

    So:

    volatile long blub;
    InterlockedIncrement(blub);
    

    Mit Hilfe davon kann man sich dann wiederum eigene Locks (Critical Sections) basteln. ⚠ Auf Linux stehen dir dann wahrscheinlich wieder andere APIs dazu zur Verfügung.

    Wenn du wissen willst wie Multi Threading im Detail und der Theorie funktioniert dann kann ich das Buch Modern Multithreading empfehlen. (Das ist allerdings sehr langweilig, englisch und formatierung ist auch nicht vorhanden 😉 )

    Mich würde mal interessieren ob Critical Sections unter Windows das Bound Waiting Prinzip umsetzen. dh. das ein Thread der am längsten wartet auch als nächstes dran kommt. 😕



  • ten schrieb:

    byto schrieb:

    Laut Bruce Eckel (Autor von Thinking in C++ & Thinking in Java) bringt Multithreading praktisch häufig auch auf 1-Prozessor-Systemen leicht bessere Performance.

    ich würde eher sagen leicht schlechtere.
    das task switching selber verbrät ja auch rechenleistung.
    beste performance hat man, wenn die cpu ungehindert rennen kann, ohne interrupts usw...
    🙂

    kommt wohl drauf an, ob man vorher ein Rechner hatte auf dem das Ding exklusiv lief oder ein Rechner hatte, auf dem eh schon ein Betriebssystem war, vielleicht sogar eines, was ständig GUI und N andere Programme laufen lässt 🙂

    Aber Threading bietet eben den Vorteil, das die Anwendung besser skaliert, wenn man weitere Rechner oder CPUs hinzufügt.



  • Aber Threading bietet eben den Vorteil, das die Anwendung besser skaliert, wenn man weitere Rechner oder CPUs hinzufügt.

    Das kommt, wie schon hier gesagt, auf den Algorithmus an. Devide&Conquer-Algos profitieren am meisten von MT, aber andere, in denen ein Ergebnis auf einen anderen aufbaut profitieren überhaupt nicht davon.



  • DEvent schrieb:

    Aber Threading bietet eben den Vorteil, das die Anwendung besser skaliert, wenn man weitere Rechner oder CPUs hinzufügt.

    Das kommt, wie schon hier gesagt, auf den Algorithmus an. Devide&Conquer-Algos profitieren am meisten von MT, aber andere, in denen ein Ergebnis auf einen anderen aufbaut profitieren überhaupt nicht davon.

    Das ein Algorithmus den man nicht in mehrere Threads aufteilen kann von Threads nicht profitiert, dürfte ja selbst redend sein...



  • Apollon schrieb:

    Und AFAIK ist ++i atomar, i++ ist es nicht.

    Das ist wohl egal. Entscheidend ist wohl eher, ob i in nem register steht oder nicht. Wenn du eine einfache for schleife hast, wird der assembler code wohl immer

    inc cx
    

    sein, egal ob du i++ oder ++i schreibst. Wenn die Schleife komplizierter ist und auch mal was anderes als i in cx steht, so das i von speicher gelesen werden muss, dann ist es nicht mehr atomar



  • Hm was mich mal interessieren würde:

    Gehen wir mal von folgender Situation aus 2 Bitmaps (800x600) die ineinander geblendet werden sollen. Währe ja ein einfach realisierbares Multithreading Szenario.

    Ab wann lohnt sich Multithreading (Ist eventuell die benötigte Zeit um die Threads starten zu lassen höher als es in einem zu Berechnen). Bzw sollte man die Thread dauerhaft laufen lassen und ihnen ihre Aufgaben zu kommen lassen.

    Wie bestimmt man wieviel Threads sich lohnen für eine Rechenoperation mit 800x600 Schleifendurchläufen. Also das von Multi Threading profitiert wird und nicht der Verwaltungsaufwand zu groß wird. (Hängt wahrscheinlich auch von Anzahl CPUs ab also muss die ja auch mit einbezogen werden)

    mfg



  • Mit dem Satz "Hängt wahrscheinlich auch von Anzahl CPUs ab also muss die ja auch mit einbezogen werden" wäre ich vorsichtig. Bei gängigen Betriebssystemen bekommt nur dein Prozess die Rechenzeit zugeteilt und dieser verteilt diese wiederum an die entsprechenden Threads. Es gibt aber auch Betriebsysteme (z.B. irgendwelche Serverbetriebssysteme) die "schwergewichtige Threads" (die genaue Bezeichnung weis ich jetzt nicht mehr) unterstützen und den einzelnen Threads direkt Prozessorzeit zuweisen.

    Ich bin allerdings erst dabei mich in die Materie einzuarbeiten. Darum kanns sein das mein Post nicht 100%ig vollständig ist (man möge mich berichtigen 😃 ).



  • Ja das ist ja sowieso klar aber wenn man zu tun hat bekommt man auch Rechenzeit vom OS und das gibt normal über alle Prozessoren. In Windows kann der User im Task Manager dann einschränken.

    Die Linuxer sind ja die die schweren Threads (eher Prozesse) nutzen mit ihrem fork Befehl, da sieht man selten das die pthreads einsetzen. Und ich denkmal bei den schweren Prozessen ist der Aufwand jedenfals höher.

    Die Frage ist eher wie schätzt man sinnvoll für einen bestimmten algorithmus mit einer bestimmten prozessoranzahl wie groß die optimale threadanzahl ist ohne performance tests auszuführen. Vieleicht gehts ja auch nur ueber Erfahrung/Schätzung, aber es währe doch toll wenns da eine Formel für gäbe und zur Laufzeit bestimmt wird wieviele Threads angebracht währen.



  • Also die gesuchte Formel lautet:

    T=C
    

    Unter der Annahme, daß C die Anzahl Cores ist und T die optimale Anzahl von Threads. Teile also so viele Aufgaben aus, wie Du Ausführungseinheiten hast.

    Wie bereits erwähnt gilt das allerdings nur, wenn die Threads wirklich ungehindert arbeiten können. Sobald ein Thread auf I/O wartet, ist es besser, man hat einen wartenden Thread, der die CPU dann beschäftigen kann.

    Als Linux-Programmierer muß ich auch noch ein Wort zu DaRpH sagen: Wie kommst Du darauf, daß die Linuxer fork zur Performancesteigerung nutzen? Also ich nutze ausschliesslich Threads zu diesem Zweck.

    Tntnet



  • Weil ichs zu oft seh 😉 bzw nutzenses zur einfachen parallelisierung von Performancesteigerung hab ich nix gesagt.

    Naja egal war ja nur ein Beispiel, nicht gleich angegriffen fühlen.



  • Leute, hier liegt wohl ein grosses grosses Misverständnis vor.
    Weder "i++" noch "++i" sind atomar.
    Read-modify-write ist auf einem x86 System immer teilbar, es sei denn man verwendet einen "interlocked" Befehl, ala InterlockedCompareExchange oder InterlockedExchangeAdd etc.



  • DaRpH schrieb:

    Die Linuxer sind ja die die schweren Threads (eher Prozesse) nutzen mit ihrem fork Befehl, da sieht man selten das die pthreads einsetzen. Und ich denkmal bei den schweren Prozessen ist der Aufwand jedenfals höher.

    Wie teuer nun ein Thread ist und ob sicher der Overhead lohnt, hängt immer von den verwendeten Threads und des Betriebssystem ab. Erlang zB (eine Programmiersprache, die auf (Buzzwordalarm) "Concurrent Programming" ausgelegt ist), benutzt User-Level-Threads, die im Grunde nichts kosten. Auch Linux erzeugt sehr schnell Prozesse und Threads. Bei Kernel-Threads hat man aber in der Regel einen großen Speicher-Overhead (idr. eine Page)



  • rüdiger schrieb:

    ...Erlang zB (eine Programmiersprache, die auf (Buzzwordalarm) "Concurrent Programming" ausgelegt ist), benutzt User-Level-Threads, die im Grunde nichts kosten.

    werden wohl ähnlich funzen wie das hier: http://www.sics.se/~adam/pt/


Anmelden zum Antworten