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.
Ein handverlesener synchroner Zeitplan, der als optimal bekannt ist, schlägt einen zufällig generierten. Groß. Wo ist das Problem? –
Der 'std :: hemlock' Vorschlag für C++ 1y sollte dieses Problem ein für allemal beenden. –
Dies scheint mit C++ 11 per se nichts zu tun zu haben. –