CAS ? Threads zusammenarbeiten lassen.



  • Kaitos schrieb:

    @+fricky
    Hört sich interessand an brauche ich irgendwelche zusätzlichen includes dafür ?

    nix spezielles, #include <windows.h>, und gut.

    Tobias: wieso 2 mutexe? unter win reicht einer (locken mit WaitForSingleObject und freigeben mit ReleaseMutex), bzw. noch besser: eine 'critical section', da mutexe eigentlich für prozessübergreifende synchronisation da sind (aber es funzt natürlich auch innerhalb eines prozesses).
    🙂



  • +fricky schrieb:

    ...
    Tobias: wieso 2 mutexe? unter win reicht einer (locken mit WaitForSingleObject und freigeben mit ReleaseMutex), bzw. noch besser: eine 'critical section', da mutexe eigentlich für prozessübergreifende synchronisation da sind (aber es funzt natürlich auch innerhalb eines prozesses).
    🙂

    Wenn du wechselseitigen Ausschluß willst kannst du dass mit einem Mutex machen? Da steh ich auf dem Schlauch...

    Wie stell ich mit einer Mutex sicher, dass der Switch zum zweiten Task erfolgt? Wird beim ReleaseMutex ?immer? ein Kontextwechsel ausgeführt?

    Wenn ja ist es mir klar... Wenn nicht, kannst du bitte ein Beispiel geben?

    Gruß
    Tobi



  • +fricky schrieb:

    ...
    Tobias: wieso 2 mutexe? unter win reicht einer (locken mit WaitForSingleObject und freigeben mit ReleaseMutex), bzw. noch besser: eine 'critical section', da mutexe eigentlich für prozessübergreifende synchronisation da sind (aber es funzt natürlich auch innerhalb eines prozesses).
    🙂

    Wenn du wechselseitigen Ausschluß willst kannst du dass mit einem Mutex machen? Da steh ich auf dem Schlauch...

    Wie stell ich mit einer Mutex sicher, dass der Switch zum zweiten Task erfolgt? Wird beim ReleaseMutex ?immer? ein Kontextwechsel ausgeführt?

    Wenn ja ist es mir klar... Wenn nicht, kannst du bitte ein Beispiel geben?

    Gruß
    Tobi



  • unsigned __stdcall RunThreadA(void *params)
    {
    	do	
    	{
    	if(p == 0)				
    		{
    		f=f-1;
    		cout << ",";
    		p=1;
    		Sleep(1);
    		}
    	}
    	while(f !=0);
    return 1;
    }
    
    unsigned __stdcall RunThreadB(void *params)
    {
    	do	
    	{		
    	if(p == 1)
    		{
    		f=f-1;
    		cout << ".";
    		p=0;
    		Sleep(1);
    		}
    	}
    	while(f !=0);
    localeSet = TRUE;
    return 1;
    }
    

    😃 Klappt aber wieso er das Sleep(1); habe will weis ich nicht ich weiß nur das es ohne das eine Endlosschleife hat.



  • Tobias Gerg schrieb:

    Wie stell ich mit einer Mutex sicher, dass der Switch zum zweiten Task erfolgt? Wird beim ReleaseMutex ?immer? ein Kontextwechsel ausgeführt?

    ja, wenn der andere task auf die freigabe des mutex wartet (wenn er z.b. in dem WaitForSingleObject-aufruf festhängt). hier: http://msdn.microsoft.com/en-us/library/ms686927.aspx
    🙂



  • Ganz allgemein: wenn es nicht mit Mutexen klappt, dann klappt es auch nicht mit anderen Synchronisationsmethoden. Die Berechnung soll parallel sein und die ausgabe sequentiell? Dann behandle Berechnung und Ausgabe getrennt. Ansonsten hast du zwar 2 Threads, die aber ein Problem sequentiell loesen, da sie sich gegenseitig blockieren.

    da mutexe eigentlich für prozessübergreifende synchronisation da sind

    Aeh nein, auch wenn unter Windows vielleicht andere Methoden der Synchronisation zuerst empfohlen werden. Beispiel Posix threads. Ausserdem steht in deinem Link nicht drin, wie garantiert wird, dass die Threads immer abwechselnd Zugriff auf die gemeinsame Ressource bekommen, sondern nur dass jeweils einer Zugriff drauf hat.



  • +fricky schrieb:

    ...
    ja, wenn der andere task auf die freigabe des mutex wartet (wenn er z.b. in dem WaitForSingleObject-aufruf festhängt). hier: http://msdn.microsoft.com/en-us/library/ms686927.aspx
    🙂

    Alles klar, dann genügt natürlich ein Mutex...

    Danke für den Link. 👍

    Gruß
    Tobi



  • knivil schrieb:

    da mutexe eigentlich für prozessübergreifende synchronisation da sind

    Aeh nein, auch wenn unter Windows vielleicht andere Methoden der Synchronisation zuerst empfohlen werden.

    ich meinte ja auch die windows-mutexe. dass der OP windows benutzt, wissen wir doch längst.

    knivil schrieb:

    Beispiel Posix threads.

    posix? wie jetzt? wofür?

    knivil schrieb:

    Ausserdem steht in deinem Link nicht drin, wie garantiert wird, dass die Threads immer abwechselnd Zugriff auf die gemeinsame Ressource bekommen, sondern nur dass jeweils einer Zugriff drauf hat.

    richtig. abwechselnd wird es nur, wenn jeder der beiden threads rechtzeitig in den lock rauscht, während der andere drin ist. aber dass so'n synchroner wechsel doof ist, hast du ja auch schon bemerkt.
    btw, damit beide threads frei rennen und sich trotzdem unterhalten können, bietet sich eventuell ein 'lock-free' FIFO an: http://kobodeluxe.sourcearchive.com/documentation/0.5.1/sfifo_8c-source.html



  • richtig. abwechselnd wird es nur, wenn jeder der beiden threads rechtzeitig in den lock rauscht, während der andere drin ist. aber dass so'n synchroner wechsel doof ist, hast du ja auch schon bemerkt.

    Aber so wie der OP es beschrieben hat, sollte es doch abwechselnd sein ,.,.,.,. . Ausserdem ist abwechseln nicht zwingend doof, da dann Threads nicht verhungern koennen. Posix threads war ein Beispiel fuer eine Threadbibliothek, die Mutexe anbietet aber nicht per se fuer Interprozesskommunikation. Und bevor jemand mit look-free Datenstrukturen oder Algorithmen hantiert, sollte er erstmal ein Gefuehl fuer normale Synchronisationsmechanismen entwickeln. Selbst die, die sich damit wirklich auskennen, machen dabei Fehler (link grad net parat).



  • knivil schrieb:

    Ausserdem ist abwechseln nicht zwingend doof, da dann Threads nicht verhungern koennen.

    Doch, denn dann sind Threads nämlich die falsche Lösung.
    Ein Thread verhungert wenn er nicht dran kommt - nicht wenn er nicht dauernd dran ist.



  • Mit abwechselnd meine ich, abwechselnd Zugriff auf eine Variable, aber die Berechnungen schon parallel.



  • knivil schrieb:

    Mit abwechselnd meine ich, abwechselnd Zugriff auf eine Variable, aber die Berechnungen schon parallel.

    Warum willst du parallele Berechnungen, wenn diese an einem Nadelöhr warten sollen? Dadurch wird deine parallele Berechnung effektiv wieder zu einer sequenziellen. Vermutlich wäre nach deiner Beschreibung dein "paralleles" Programm selbst auf einer Mehrprozessormaschine kaum schneller als ein sequenzielles Programm (vielleicht sogar langsamer).



  • Warum willst du parallele Berechnungen, wenn diese an einem Nadelöhr warten sollen?

    Warum sollte es ein Nadeloehr sein? Wenn das Holen/Schreiben des Wertes kurze Zeit beansprucht und die Berechnung lange dauert? (jedesmal etwa gleich lang)

    Dadurch wird deine parallele Berechnung effektiv wieder zu einer sequenziellen.

    Nein, da keine Datenabhaengigkeit zwischen den Threads bestehen muss.

    Vermutlich wäre nach deiner Beschreibung dein "paralleles" Programm selbst auf einer Mehrprozessormaschine kaum schneller als ein sequenzielles Programm (vielleicht sogar langsamer).

    Unbegruendete Behauptung. Und warum sollte es auf Mehrkernsystemen langsamer sein als auf Einkernsystemen (gleiche Taktzahl etc vorausgesetzt)? Wieviel Erfahrung hast du mit Multi thread programming? Selbst Anwendungen auf Einkernsysteme koennen von mehreren Threads profitieren (anwendungsspezifisch).



  • knivil schrieb:

    Unbegruendete Behauptung. Wieviel Erfahrung hast du mit Multi thread programming? Selbst Anwendungen auf Einkernsysteme koennen von mehreren Threads profitieren (anwendungsspezifisch).

    Nicht wenn du wie du es vorschlägst künstliche sperren einbaust.

    Das Problem bei diesem abwechslenden zugriff sind die standzeiten der threads. du hast standzeiten, egal wie du es implementierst. und das ist der design fehler.

    lass die threads parallel laufen und synchronisieren den zugriff auf die zentrale variable korrekt und du hast ein viel besseres system. nur eben dass das ergebnis halt nicht ABABABABABA sondern AAABBAAABBBBBBBAABBAAAA ist...

    wenn es wichtig ist dass ABABA raus kommt, dann macht man es über einen 3. thread der von der einen seite lauter A und von der anderen Seite lauter B bekommt und diese dann verschmilzt - nach dem gewünschten muster.

    uU muss es auch kein thread sein sondern die datenstruktur kann das uU auch selber... jedenfalls ist ein erzwingen eines nacheinander ablaufens eines parallelen programms keine gute idee.



  • du hast standzeiten, egal wie du es implementierst.

    Das gebe ich zu.

    erzwingen eines nacheinander ablaufens eines parallelen programms keine gute idee.

    Das gebe ich auch zu. (irgendwelche Ausnahmen bestaetigen bestimmt diese Regel)



  • knivil schrieb:

    Wieviel Erfahrung hast du mit Multi thread programming? Selbst Anwendungen auf Einkernsysteme koennen von mehreren Threads profitieren (anwendungsspezifisch).

    Ich behaupte jetzt einfach mal frech: Ich habe deutlich mehr Grundlagenwissen über Multithreadprogrammierung wie du, auch wenn sich der Einsatz (bedingt durch Projektvorgaben) auf ein Minimum beschränkt.

    Davon abgesehen kann ein Prozessor (wenn wir mal Techniken wie Hyperthreading außen vor lassen) nur maximal zu 100% ausgelastet werden, egal ob sequenziell oder parallel. Und das Umschalten zwischen Threads kostet auch Zeit. Was man auf einem Prozessor tatsächlich schaffen kann ist aber eine bessere Auslastung wenn ein Thread wegen irgendwas warten muss.

    Multithreading hat auf Einzelprozessormaschinen vor allem seine Vorzüge, wenn bestimmte Aktionen durchgeführt werden können während andere z.B. auf Benutzereingaben oder DB-Rückmeldungen etc. warten.

    Du wiederum verringerst jeglichen theoretischen Mehrwert den Threads haben, durch dein sequenzielles "Nadelöhr". Je nach dem wie groß der Verwaltungsaufwand für die Synchronisation ist, kann dies den Nutzen überwiegen - oder zumindest stark reduzieren. Ich würde entweder die Berechnungen gänzlich trennen - und erst am Schluss die Daten zusammenführen - oder die Threads in einen verschmelzen.

    cu André



  • asc schrieb:

    Du wiederum verringerst jeglichen theoretischen Mehrwert den Threads haben, durch dein sequenzielles "Nadelöhr". Je nach dem wie groß der Verwaltungsaufwand für die Synchronisation ist, kann dies den Nutzen überwiegen - oder zumindest stark reduzieren. Ich würde entweder die Berechnungen gänzlich trennen - und erst am Schluss die Daten zusammenführen - oder die Threads in einen verschmelzen.

    Ok, ich will dir deine Erfahrung nicht streitig machen, im nachhinein gesehen ist mein Satz ueberfluessig. Das Hauptproblem ist, dass Threads sehr anwendungsspeziell sind und hier natuerlich nur (mehr oder weniger) allgemein diskutiert werden kann. Es wichtig, Verwaltungskosten von Threads gegen den Berechnungsnutzen abzuwaegen, was aber sehr speziell ist. Sequentielle Anteile hat man immer. Die Frage ist meist, wohin diese legen ... Ein Nadeloehr muessen sie aber trotzdem nicht sein. Auch wie grob- oder feinkoernig parallelisiert werden kann/muss, ist Problem und Hardware abhaengig. Deswegen kann manchmal Strategie A besser sein als B. Aber es gibt Variante B und ist anderswo besser als A. Im Durchschnitt (ueber alle Probleme) hebt sich bestimmt keine Variante hervor.

    PS: Jaja, alles allgemein und (fast) nichts sagend, aber ... ach keine Ahnung. Irgendwie gibt das konkrete Ausgangsproblem nicht mehr her.

    verringerst jeglichen theoretischen Mehrwert den Threads haben

    Linearer Speedup ist selten erreichbar. Irgendwo muss man immer Abstriche machen.



  • Shade Of Mine schrieb:

    wenn es wichtig ist dass ABABA raus kommt, dann macht man es über einen 3. thread der von der einen seite lauter A und von der anderen Seite lauter B bekommt und diese dann verschmilzt...

    damit kannste dich dann hier bewerben: http://thedailywtf.com/Default.aspx
    🙂



  • +fricky schrieb:

    Shade Of Mine schrieb:

    wenn es wichtig ist dass ABABA raus kommt, dann macht man es über einen 3. thread der von der einen seite lauter A und von der anderen Seite lauter B bekommt und diese dann verschmilzt...

    damit kannste dich dann hier bewerben: http://thedailywtf.com/Default.aspx
    🙂

    Ist n ziemliches standard verfahren, wenn wir das "verschmelzen" als nachverarbeiten der daten betrachten.

    bedenke dabei, dass bereits bei einem:

    thread1.start();
    thread2.start();
    
    wait_for_threads_to_finish();
    
    process_data();
    

    dieses muster angewandt wird.

    btw:
    ich dachte, du wolltest in fachforen nicht trollen...?



  • Shade Of Mine schrieb:

    ich dachte, du wolltest in fachforen nicht trollen...?

    das war kein trolling. seit der ersten antwort wissen wir schon, dass multithreading hier völlig unnötig ist.
    🙂


Anmelden zum Antworten