Multithreading und Synchronisierung



  • Wow, das ging aber schnell!
    Beruhigt mich jedenfalls, dass schlimmstenfalls "nur" kompletter Nonsens auf der Variable steht.

    Herzlichen Dank,
    Günther



  • Günny schrieb:

    Wow, das ging aber schnell!
    Beruhigt mich jedenfalls, dass schlimmstenfalls "nur" kompletter Nonsens auf der Variable steht.

    Herzlichen Dank,
    Günther

    Ich wüsste aber nicht, was daran "nur" sein soll. 😉 Ich meine du kannst dann statt der if-Abfrage auch einfach würfeln.



  • Naja, ein Zugriff auf einen Pointer, der ggf. noch nicht initialisiert ist kann schonmal das Programm abstürzen lassen, oder deine Partition formatieren oder dein BS zerschiessen, oder... übertreib.

    Beim auslesen eines zufälligen UINT Wertes wird nichts dergleichen passieren. Du arbeitest halt mit einem Pseudo-Zufallswert.

    Gruß
    Don06



  • bei nem standard PC den jeder zuhause hat, kannst du davon ausgehen, dass kein Unsinn darin stehen wird. Ich glaub es gibt keine möglichkeit gleichzeitig in eine Speicherzelle zu schreiben und daraus zu lesen. und da ein UINT in ein register passt, sollte immer was sinnvolles drinstehen, außer du hast eine Architektur, bei der ein UINT nicht in ein Register passt.



  • Kein Wunder das es soviel schlechte Software gibt bei soviel Achtlosigkeit... Keiner stellt mal die Entshceidende Frage was denn bei der if-Abfrage passieren soll.

    Es stimmt schon soweit das die Variable immer einen gültigen Wert haben wird, aber... z.B. folgendes Beispiel:

    char array[25];
    
    if( i < 25)
    {
       array[i] = 42;
    }
    

    Das würde ja bedeuten das der if-Teil nur ausgeführt werden soll wenn i < 25 ist. Wenn aber zeitgleich ein andere Thread ebenfalls i verändert, dann kann es passieren das zum Zeitpunkt der if-Abfrage i zwar noch kleiner 25 ist, direkt danach, bei Ausführung des if-blocks i aber > 25 sein kann.

    Fazit, der Code, der eigentlich nur ausgeführt werden sollte wenn i < 25 ist wird ausgeführt mit einem i > 25.

    Mich würde sowas nicht beruhigen...



  • skals schrieb:

    Kein Wunder das es soviel schlechte Software gibt bei soviel Achtlosigkeit... Keiner stellt mal die Entshceidende Frage was denn bei der if-Abfrage passieren soll.

    Es stimmt schon soweit das die Variable immer einen gültigen Wert haben wird, aber... z.B. folgendes Beispiel:

    char array[25];
    
    if( i < 25)
    {
       array[i] = 42;
    }
    

    Das würde ja bedeuten das der if-Teil nur ausgeführt werden soll wenn i < 25 ist. Wenn aber zeitgleich ein andere Thread ebenfalls i verändert, dann kann es passieren das zum Zeitpunkt der if-Abfrage i zwar noch kleiner 25 ist, direkt danach, bei Ausführung des if-blocks i aber > 25 sein kann.

    Fazit, der Code, der eigentlich nur ausgeführt werden sollte wenn i < 25 ist wird ausgeführt mit einem i > 25.

    Mich würde sowas nicht beruhigen...

    Nachdem es ihm ja sogar egal war, wenn in seinem UINT totaler Unsinn steht, kann die Variable hoffentlich nicht so wichtig sein. Aber irgendwie ist die Frage schon berechtigt für was man sowas brauchen kann.



  • also schrieb:

    bei nem standard PC den jeder zuhause hat, kannst du davon ausgehen, dass kein Unsinn darin stehen wird. Ich glaub es gibt keine möglichkeit gleichzeitig in eine Speicherzelle zu schreiben und daraus zu lesen. und da ein UINT in ein register passt, sollte immer was sinnvolles drinstehen, außer du hast eine Architektur, bei der ein UINT nicht in ein Register passt.

    Das ist ja wohl kompletter Unsinn. Wozu gibt denn Speicher wenn keiner reinschreiben darf? Und natürlich kann Unsinn im Speicher stehen. Einfachstes Beospiel: int i; -> in i steht Unsinn, weil uninitialisiert.



  • Optimizer schrieb:

    Das schlimmste was passieren könnte ist, dass da drin kompletter Unsinn steht. Das ist aber auch vom Typ der Variablen und vom Prozessor abhängig. Bei nem UINT im speziellen ist es wahrscheinlich auf den meisten Prozessoren so, dass eine Zuweisung atomar ist, also hast du voll den alten oder voll den neuen Wert. Aber die Garantie gibt's nicht.

    es ist nicht garantiert dass die zuweisung atomar ist, der uint32_t wert kann genau so gut auf zwei speichersegmente aufgeteilt sein. atomar darf man bei uint8_t annehmen.







  • Es gibt noch folgenden Text von Intel zu ihren Garantien bezüglich der Anordnung von Befehlen und den Speichereffekten:

    http://developer.intel.com/products/processor/manuals/318147.pdf

    Was ich aber vermisse ist eine Aussage zu:

    Zwei Befehle schreiben gleichzeitig in die selbe Speicherzelle.

    Was passiert da? Wahrscheinlich gewinnt eine der der beiden Schreibzugriffe und der Wert wird dann irgendwann in der Speicherzelle stehen.

    Mir wäre es aber viel lieber wenn eine solche Situation ein SIGSEGV erzeugen würde. Gleiches würde ich für einen gleichzeitigen Schreib- und Lesezugriff wünschen.

    Es ist klar, dass dann erstmal nichts mehr funktionieren würde, da viele Programme einfach bezüglich Multithreading kaputt sind. Aber dann hätte man wenigstens die Chance es zu richten. Und das Debugging wäre einfacher.



  • Ponto schrieb:

    rüdiger schrieb:

    http://ridiculousfish.com/blog/archives/2007/02/17/barrier/

    Dazu sollte man folgendes beachten: http://www.thinkingparallel.com/2007/02/19/please-dont-rely-on-memory-barriers-for-synchronization/

    Oha, interessant. Aber ich wollte vor allem auf Memory-Barriers und Reordering aufmerksam machen!



  • Ponto schrieb:

    Es gibt noch folgenden Text von Intel zu ihren Garantien bezüglich der Anordnung von Befehlen und den Speichereffekten:

    http://developer.intel.com/products/processor/manuals/318147.pdf

    Was ich aber vermisse ist eine Aussage zu:

    Zwei Befehle schreiben gleichzeitig in die selbe Speicherzelle.

    Was passiert da? Wahrscheinlich gewinnt eine der der beiden Schreibzugriffe und der Wert wird dann irgendwann in der Speicherzelle stehen.

    Mir wäre es aber viel lieber wenn eine solche Situation ein SIGSEGV erzeugen würde. Gleiches würde ich für einen gleichzeitigen Schreib- und Lesezugriff wünschen.

    Es ist klar, dass dann erstmal nichts mehr funktionieren würde, da viele Programme einfach bezüglich Multithreading kaputt sind. Aber dann hätte man wenigstens die Chance es zu richten. Und das Debugging wäre einfacher.

    hardware synchronisation waere unglaublich langsam, schalt einfach deinen cache aus (im bios geht das bei manchen), dann siehst du wie die performance dann einbricht. deswegen ist software fuer synchronisation verantwortlich.



  • rapso schrieb:

    hardware synchronisation waere unglaublich langsam, schalt einfach deinen cache aus (im bios geht das bei manchen), dann siehst du wie die performance dann einbricht. deswegen ist software fuer synchronisation verantwortlich.

    Woraus liest du, dass ich Hardwaresynchronisation befürworte? Ich meine sogar, dass Hardware gegenüber Synchronisationsfehlern noch weniger tolerant sein sollte, als sie es zur Zeit ist. Und weniger Toleranz bringt vielleicht mehr Performanz.



  • Ponto schrieb:

    rapso schrieb:

    hardware synchronisation waere unglaublich langsam, schalt einfach deinen cache aus (im bios geht das bei manchen), dann siehst du wie die performance dann einbricht. deswegen ist software fuer synchronisation verantwortlich.

    Woraus liest du, dass ich Hardwaresynchronisation befürworte? Ich meine sogar, dass Hardware gegenüber Synchronisationsfehlern noch weniger tolerant sein sollte, als sie es zur Zeit ist. Und weniger Toleranz bringt vielleicht mehr Performanz.

    daraus dass du moechtest dass hardware ein SIGSEGV wirft. dafuer muesste die hardware synchronisieren ob zufaellig zwei cpus auf die selbe speicherstelle zugreifen.



  • rapso schrieb:

    daraus dass du moechtest dass hardware ein SIGSEGV wirft. dafuer muesste die hardware synchronisieren ob zufaellig zwei cpus auf die selbe speicherstelle zugreifen.

    Nur, wenn die das durch Zufall feststellt. Ich weiss aber nicht wie der Zugriff auf den Speicher physikalisch genau funktioniert, so dass ich über die Praktikabilität nichts sagen kann.



  • rapso schrieb:

    Optimizer schrieb:

    Das schlimmste was passieren könnte ist, dass da drin kompletter Unsinn steht. Das ist aber auch vom Typ der Variablen und vom Prozessor abhängig. Bei nem UINT im speziellen ist es wahrscheinlich auf den meisten Prozessoren so, dass eine Zuweisung atomar ist, also hast du voll den alten oder voll den neuen Wert. Aber die Garantie gibt's nicht.

    es ist nicht garantiert dass die zuweisung atomar ist, der uint32_t wert kann genau so gut auf zwei speichersegmente aufgeteilt sein. atomar darf man bei uint8_t annehmen.

    Das sollte auf Grund des alignments durch den Compiler nicht passieren. Aber klar, ich würde auf jeden Fall den Zugriff synchronisieren. So viel Gründlichkeit muss einfach sein.



  • Optimizer schrieb:

    rapso schrieb:

    es ist nicht garantiert dass die zuweisung atomar ist, der uint32_t wert kann genau so gut auf zwei speichersegmente aufgeteilt sein. atomar darf man bei uint8_t annehmen.

    Das sollte auf Grund des alignments durch den Compiler nicht passieren. Aber klar, ich würde auf jeden Fall den Zugriff synchronisieren. So viel Gründlichkeit muss einfach sein.

    Ich weis zwar nicht wie, aber ich hab mit 10 Threads gleichzeitig eine Variable Hochgezählt. Also jeder Thread hat die Variable um eins erhöht. Der Wert wurde vorher auf 0 gesetzt. Als ich die Variable mal ohne Lock ausgelesen hab, wärend die anderen Threads noch liefen, hatte ich plötzlich einen negativen Wert. (System: i686-Prozessor mt einem Kern, GCC-Compiler)



  • Optimizer schrieb:

    rapso schrieb:

    Optimizer schrieb:

    Das schlimmste was passieren könnte ist, dass da drin kompletter Unsinn steht. Das ist aber auch vom Typ der Variablen und vom Prozessor abhängig. Bei nem UINT im speziellen ist es wahrscheinlich auf den meisten Prozessoren so, dass eine Zuweisung atomar ist, also hast du voll den alten oder voll den neuen Wert. Aber die Garantie gibt's nicht.

    es ist nicht garantiert dass die zuweisung atomar ist, der uint32_t wert kann genau so gut auf zwei speichersegmente aufgeteilt sein. atomar darf man bei uint8_t annehmen.

    Das sollte auf Grund des alignments durch den Compiler nicht passieren. Aber klar, ich würde auf jeden Fall den Zugriff synchronisieren. So viel Gründlichkeit muss einfach sein.

    aber garantieren kann man es nicht. einfach mal ein compilerflag aendern, oder ein memorymapped file, oder noch einfacher, umcasten von pointern. gibt bei manchen systemen nen absturz, aber beim x86 laeuft das normal weiter.



  • ProgChild schrieb:

    Optimizer schrieb:

    rapso schrieb:

    es ist nicht garantiert dass die zuweisung atomar ist, der uint32_t wert kann genau so gut auf zwei speichersegmente aufgeteilt sein. atomar darf man bei uint8_t annehmen.

    Das sollte auf Grund des alignments durch den Compiler nicht passieren. Aber klar, ich würde auf jeden Fall den Zugriff synchronisieren. So viel Gründlichkeit muss einfach sein.

    Ich weis zwar nicht wie, aber ich hab mit 10 Threads gleichzeitig eine Variable Hochgezählt. Also jeder Thread hat die Variable um eins erhöht. Der Wert wurde vorher auf 0 gesetzt. Als ich die Variable mal ohne Lock ausgelesen hab, wärend die anderen Threads noch liefen, hatte ich plötzlich einen negativen Wert. (System: i686-Prozessor mt einem Kern, GCC-Compiler)

    hmm.. bei nur einem core ist das ohne hardware/software bugs eigentlich nicht moeglich. es gibt ja zu jeder zeit nur ein abbild des speichers im cache. vielleicht war die variable uninitialisiert? 😃


Anmelden zum Antworten