tutorials.de Buch-Aktion 05/2012
ERLEDIGT
NEIN
ANTWORTEN
6
ZUGRIFFE
269
EMPFEHLEN
  • An Twitter übertragen
  • An Facebook übertragen
AUF DIESES THEMA
ANTWORTEN
  1. #1
    Avatar von port29
    port29 port29 ist offline deus.Server
    Registriert seit
    Dec 2001
    Ort
    Karlsruhe, Germany, Germany
    Beiträge
    856
    Hallo,

    heute hat ein Kumpel mich um Hilfe gebeten. In der Uni hat er eine Aufgabe bekommen und diese auch bestmöglich gelöst. Die Aufgabe ist zwar "dumm", doch wir sind zufällig auf ein interessantes Phänomen gestoßen.

    Die Aufgabe war es, Threads generieren zu lassen, die eine Last erzeugen und diese 30 Sekunden halten. In dem konkreten Programm erzeugt mein Kumpel die Last, indem er pi berechnet:

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
            int n = 310000000;                          
                    
            int counter = 0;                            
            for(int i = 0; i<n; i++){                   
     
                double x = rand.nextDouble();
                double y = rand.nextDouble();
                if(x*x+y*y <= 1) counter++;
            }

    Wie sinnvoll der Quelltext jetzt ist, sei nun mal dahingestellt. Es steht fest, dass wenn man den Code ausführt, er bei ihm 35 Sekunden läuft und bei mir 23. Die gleiche Laufzeit hat das Programm auch, wenn die Berechnung in einem extra Thread durchgeführt wird.

    Jetzt lasse ich den gleichen Code in zwei Threads parallel ablaufen.

    Vorhersage:
    - Worst Case Laufzeit 23sek*2 + Overhead = 50sek
    - Best Case 23 sek

    Und die 23 Sekunden habe ich auch erwartet. Denn der Rechner hatte noch drei CPU Kerne, die er verwenden konnte. In der Realität sah ich aber etwas anderes. Im Task Manager konnte ich beobachten, wie die Auslastung der CPUs hochging. Die Berechnung war nach 150sek zu Ende. Und die Rechenzeit steigt exponentiell mit der anzahl der Threads an.

    1 Thread = 23 sek
    2 Threads = 151 sek
    3 Threads = 442 sek

    Als ich den Double Aufruf rausgenommen habe, hatte ich die erwarteten Resultate. Kann mir von euch jemand sagen, wieso ich so ein Verhalten bekomme?
     

  2. #2
    deepthroat deepthroat ist offline Mitglied Diamant
    tutorials.de Premium-User
    Registriert seit
    Jun 2005
    Beiträge
    8.168
    Hi.

    Kannst du mal den kompletten Quelltext hier posten?

    Meine Vermutung wäre, das alle Threads die gleiche rand Variable verwenden.

    Gruß
     
    If at first you don't succeed, try again. Then quit. No use being a damn fool about it.

  3. #3
    Avatar von port29
    port29 port29 ist offline deus.Server
    Registriert seit
    Dec 2001
    Ort
    Karlsruhe, Germany, Germany
    Beiträge
    856
    Zitat Zitat von deepthroat Beitrag anzeigen
    Meine Vermutung wäre, das alle Threads die gleiche rand Variable verwenden.
    Hi,

    danke für den Tipp. Das Problem war tatsächlich:
    Code :
    1
    
    private static Random rand = new Random();

    bzw. Math.random() in dem Original Quelltext.

    Dennoch kann ich dann trotzdem nicht verstehen, woher denn nun die überflüssige Last kam.

    Wenn ich rand statisch deklariere, welcher Thread ist dann für rand zuständig?
     

  4. #4
    deepthroat deepthroat ist offline Mitglied Diamant
    tutorials.de Premium-User
    Registriert seit
    Jun 2005
    Beiträge
    8.168
    Zitat Zitat von port29 Beitrag anzeigen
    Hi,

    danke für den Tipp. Das Problem war tatsächlich:
    Code :
    1
    
    private static Random rand = new Random();

    bzw. Math.random() in dem Original Quelltext.

    Dennoch kann ich dann trotzdem nicht verstehen, woher denn nun die überflüssige Last kam.

    Wenn ich rand statisch deklariere, welcher Thread ist dann für rand zuständig?
    Nun, alle Threads "teilen" sich die Variable, d.h. alle sind dafür zuständig. Java sorgt allerdings dafür, das der Zugriff auf die Variable synchronisiert wird. Je mehr Threads verwendet werden desto höher ist die Zahl der Kollisionen beim Zugriff.

    Gruß
     
    If at first you don't succeed, try again. Then quit. No use being a damn fool about it.

  5. #5
    Avatar von port29
    port29 port29 ist offline deus.Server
    Registriert seit
    Dec 2001
    Ort
    Karlsruhe, Germany, Germany
    Beiträge
    856
    Zitat Zitat von deepthroat Beitrag anzeigen
    Nun, alle Threads "teilen" sich die Variable, d.h. alle sind dafür zuständig. Java sorgt allerdings dafür, das der Zugriff auf die Variable synchronisiert wird. Je mehr Threads verwendet werden desto höher ist die Zahl der Kollisionen beim Zugriff.
    Ich muss ehrlich zugeben, dass ich aus der ASM Welt komme und nicht daran gewöhnt bin, dass mir irgendeine VM dazwischenfunkt. Und der Zufallsgenerator ist für mich auch nur etwas, was ich lesen kann. Deshalb ist - aus meiner Sicht - keine Synchronisation notwendig. Aber da Java es so haben möchte.....

    Was ich aber trotzdem nicht verstehe, ist wie die Kollisionen umgangen werden. Okay, wenn ich irgendwelche Bus Systeme implementiere, dann ziehen sich alle am Konflikt teilnehmenden Teilnehmer zurück und warten eine zufällige Zeit. Dann versuchen die es noch einmal. Hier bei Threads wird wohl ein Thread ein Lock gesetzt haben und die anderen haben einfach keinen Zugriff. Doch wieso habe ich trotzdem eine Last auf den Prozessoren?
     

  6. #6
    deepthroat deepthroat ist offline Mitglied Diamant
    tutorials.de Premium-User
    Registriert seit
    Jun 2005
    Beiträge
    8.168
    Zitat Zitat von port29 Beitrag anzeigen
    Ich muss ehrlich zugeben, dass ich aus der ASM Welt komme und nicht daran gewöhnt bin, dass mir irgendeine VM dazwischenfunkt. Und der Zufallsgenerator ist für mich auch nur etwas, was ich lesen kann. Deshalb ist - aus meiner Sicht - keine Synchronisation notwendig. Aber da Java es so haben möchte.....
    Nein, der Zufallsgenerator beinhaltet einen Zustand (den Random Seed), deshalb muss der Zugriff synchronisiert werden.
    Zitat Zitat von port29 Beitrag anzeigen
    Was ich aber trotzdem nicht verstehe, ist wie die Kollisionen umgangen werden. Okay, wenn ich irgendwelche Bus Systeme implementiere, dann ziehen sich alle am Konflikt teilnehmenden Teilnehmer zurück und warten eine zufällige Zeit. Dann versuchen die es noch einmal. Hier bei Threads wird wohl ein Thread ein Lock gesetzt haben und die anderen haben einfach keinen Zugriff. Doch wieso habe ich trotzdem eine Last auf den Prozessoren?
    Ja, bei statischen Attributen wird ein Lock auf die Klasse gesetzt. Häufig wird dabei "aktives Warten" verwendet, d.h. die Threads schlafen nicht eine gewisse Zeit, sondern fragen in einer Schleife ständig den Lock ab. Das würde dann die CPU-Last erklären.

    Gruß
     
    If at first you don't succeed, try again. Then quit. No use being a damn fool about it.

  7. #7
    Registriert seit
    Oct 2003
    Beiträge
    1.706
    Hallo,

    Zitat Zitat von port29 Beitrag anzeigen
    Und der Zufallsgenerator ist für mich auch nur etwas, was ich lesen kann. Deshalb ist - aus meiner Sicht - keine Synchronisation notwendig. Aber da Java es so haben möchte.....
    Es wird eben nicht nur lesend zugegriffen da bei einem Aufruf von nextDouble ja ein neuer Zufallswert berechnet wird. Durch eine evtl. auftretende Raise Condition könnte die deterministische Berechnung der Folge von Pseudozufallszahlen verfälscht werden und somit ist hier imo eine Synchronisation erforderlich.

    Zitat Zitat von port29 Beitrag anzeigen
    Was ich aber trotzdem nicht verstehe, ist wie die Kollisionen umgangen werden. Okay, wenn ich irgendwelche Bus Systeme implementiere, dann ziehen sich alle am Konflikt teilnehmenden Teilnehmer zurück und warten eine zufällige Zeit. Dann versuchen die es noch einmal. Hier bei Threads wird wohl ein Thread ein Lock gesetzt haben und die anderen haben einfach keinen Zugriff. Doch wieso habe ich trotzdem eine Last auf den Prozessoren?
    Um einen wechselseitigen Ausschluss garantieren zu können ist auch ein nicht unerheblicher Aufwand an Verwaltung von Threads erforderlich. Bspw. müssen Algorithmen ablaufen die eine Fairness aller beteiligten Threads garantieren usw. Das schlägt sich nat. auf die Laufzeit eines Programmes nieder.

    //edit da war ich wohl zu spät

    Gruß,
    RedWing
     

Ähnliche Themen

  1. Probleme mit Threads
    Von eagle1985 im Forum Java
    Antworten: 9
    Letzter Beitrag: 18.02.10, 14:07
  2. Probleme mit QT-Threads
    Von cesupa im Forum C/C++
    Antworten: 3
    Letzter Beitrag: 15.12.07, 11:34
  3. Probleme mit synconisierten Threads
    Von MonsyX im Forum Java
    Antworten: 0
    Letzter Beitrag: 03.12.07, 20:33
  4. Probleme mit Threads!
    Von dapor im Forum Java
    Antworten: 1
    Letzter Beitrag: 17.05.06, 20:19
  5. Probleme beim Starten eines Threads
    Von DannyP im Forum C/C++
    Antworten: 6
    Letzter Beitrag: 02.02.05, 00:07