2013-06-09 14 views
8

Ich interessiere mich für die Leistung von Mutex und Message-Weitergabe in der neuesten gcc mit Threads auf Pthreads und eine Ubuntu-Entwicklungsumgebung basiert. Ein gutes generisches Problem dafür sind die Speisephilosophen, wo jeder Philosoph die links und rechts benachbarten Nachbarn benutzt. Ich erhöhe die Anzahl der Philosophen auf 99, um meinen Vierkernprozessor beschäftigt zu halten.Leistung von Threads in C++ 11

Der obige Code erlaubt meinem Philosophen, die zwei Gabeln zu ergreifen, die sie essen müssen.

der oben genannte Code überwacht meine Philosophen Fortschritt essen oder denken je nachdem, ob sie es schaffen, die beiden Gabeln zu reservieren.

{ 
     testEnd te(eating[j]+thinking[j]-1); 
     unique_lock<mutex> lk(cycleDone); 
     endCycle.wait(lk, te); 
    } 

der obige Code wartet auf alle Philosophen die Auswahl nach dieser Zeit abzuschließen der Philosoph frei ist, um einen neuen Versuch zu machen:

if (philosophers::State::Eating == state[j]) 
    { 
     state[j] = philosophers::State::Thinking; 
     forks[lhf].unlock(); 
     forks[rhf].unlock(); 
    } 

Ich habe einen Haupt-Thread, der die Philosophen und bewegt überwacht sie von einem Zyklus zum nächsten, die ihnen ungefähr 10 Sekunden erlaubt, zu essen und zu denken, soviel sie können. Das Ergebnis ist etwa 9540 Zyklen mit einigen hungernden Philosophen und anderen, die viel zu essen und viel Zeit zum Nachdenken haben! Also muß ich meine Philosophen vor dem Verhungern zu schützen und zu lange warten, so füge ich mehr Logik zu essen zu verhindern, über durch das Essen Philosophen erfordern freizugeben und zu denken, anstatt GAB die gleichen Gabeln nach einer sehr kleinen Pause:

// protect the philosopher against starvation 
    if (State::Thinking == previous) 
    { 
     result = try_lock(forks[lhf], forks[rhf]); 
    } 

Jetzt habe ich 9598 Zyklen, wobei jeder Philosoph einen relativ gleichen Anteil an Essen bekommt (2620 - 2681) und mit der längsten Wartezeit von 14 denkt. Nicht schlecht. Aber ich bin nicht zufrieden damit, jetzt werde ich alle Mutex und Locks los und behalte es einfach mit den geraden Philosophen, die in geraden Zyklen essen und die ungeraden Philosophen, die in den ungeraden Zyklen essen. Ich benutze eine einfache Methode, die Philosophen von Syncing

while (counter < counters[j]) 
{ 
    this_thread::yield(); 
} 

ein Philosoph Verhindert, dass Essen oder zu oft denken, einen globalen Zykluszähler verwendet wird. Zur gleichen Zeit und die Philosophen verwalten etwa 73543 Zyklen mit 36400 Essen und nicht mehr als 3 Zyklen warten. Mein einfacher Algorithmus ohne Sperren ist also schneller und hat eine bessere Verteilung der Verarbeitung zwischen den verschiedenen Threads.

Kann mir jemand einen besseren Weg vorstellen, dieses Problem zu lösen? Ich fürchte, wenn ich ein komplexes System mit mehreren Threads implementiere, werde ich, wenn ich traditionellen Mutex- und Message-Passing-Techniken folge, mit einer langsameren als notwendigen und möglichen unausgewogenen Verarbeitung auf den verschiedenen Threads in meinem System enden.

+3

Ein handverlesener synchroner Zeitplan, der als optimal bekannt ist, schlägt einen zufällig generierten. Groß. Wo ist das Problem? –

+1

Der 'std :: hemlock' Vorschlag für C++ 1y sollte dieses Problem ein für allemal beenden. –

+0

Dies scheint mit C++ 11 per se nichts zu tun zu haben. –

Antwort

2

Dies ist eine interessante Möglichkeit, die Probleme des Threads in C++ zu erkunden.

spezifische Punkte ansprechen:

Ich fürchte, dass, wenn ich ein komplexes System mit mehreren Threads implementieren, wenn ich traditionelle Mutex und Message-Passing-Techniken folgen werde ich mit langsamer als nötig und möglich unausgeglichen Verarbeitung am Ende auf die verschiedenen Threads in meinem System.

Leider ist die beste Antwort, die ich Ihnen geben kann, dass dies eine begründete Angst ist.Die Kosten für Planung und Synchronisation sind jedoch sehr spezifisch für die Anwendung - dies wird zu einer technischen Entscheidung beim Entwurf eines großen Systems. In erster Linie ist die Planung NP-Hard (http://en.wikipedia.org/wiki/Multiprocessor_scheduling), hat aber gute Näherungen.

Was Ihr spezielles Beispiel betrifft, ist es schwierig, allgemeine Schlüsse aus den Ergebnissen zu ziehen, die Sie präsentieren - es gibt einen primären Ausgangspunkt: den Kompromiss zwischen Grobkornsynchronisation und Feinkornsynchronisation. Dies ist ein gut untersuchtes Problem, und einige Untersuchungen können hilfreich sein (z. B. http://ieeexplore.ieee.org/xpls/abs_all.jsp?arnumber=744377&tag=1).

Insgesamt handelt es sich um ein technisches Problem, das spezifisch für das zu lösende Problem, das Betriebssystem und die Hardware ist.