2013-01-14 5 views
14

Ich arbeitete mit etwas Parallelisierung und das brachte mich dazu, Amdahls Gesetz zu untersuchen. Ich habe eine Reihe von Beiträgen zu diesem Thema gelesen.Amdahls Gesetz Beispiel in C#

Calculate performance gains using Amdahl's Law

How to calculate Amadahl's Law for threading effectiveness

http://en.wikipedia.org/wiki/Amdahl%27s_law

... aber hatte gehofft, ein C# Beispiel zu finden, es in der Praxis zeigen. Das Suchen hat keine Ergebnisse gezeigt. Theoretisch sollte es möglich sein, eine serielle Anwendung zu erstellen, die parallelisierbaren Teile zu synchronisieren, eine parallelisierte Version zu erstellen, die Länge der parallelen Teile aufzuzeichnen und den Unterschied (Wissen, wie viele Prozessoren verwendet werden) mit dem Ergebnis der Amdahl-Funktion zu vergleichen. Ist das korrekt und ist jemandem bekannt, dass ein solches Beispiel existiert?

+0

Das ist eine gute Frage. Upvoted und bevorzugt. – Brian

+1

Palatalisierung? –

Antwort

10

Hinweis: Eine komplette Arbeits Download-Version des Programms kann auf My Github Page

So mit Amdahl Gesetz zu finden, teilen wir uns die Arbeit um und „Arbeit„Arbeit, die in Serien laufen müssen“, die parallelisiert werden können“, also lassen Sie uns diese beiden Workloads als List<Action> darstellen:

var serialWorkLoad = new List<Action> { DoHeavyWork, DoHeavyWork }; 
var parallelizableWorkLoad = new List<Action> { DoHeavyWork, DoHeavyWork, DoHeavyWork, DoHeavyWork, DoHeavyWork, DoHeavyWork, DoHeavyWork, DoHeavyWork }; 

Wo die DoHeavyWork delegieren brillant wie abstrahiert:

static void DoHeavyWork() 
{ 
    Thread.Sleep(500); 
} 

Wie Sie sehen können, habe ich die parallelisierbare Arbeitslast ein bisschen schwerer für Spaß gemacht und ein anständiges Beispiel dafür gemacht.

Als nächstes müssen wir beide Workloads in Serien laufen unsere Basislinie zu erhalten:

var stopwatch = new Stopwatch(); 
stopwatch.Start(); 
// Run Serial-only batch of work 
foreach (var serialWork in serialWorkLoad) 
{ 
    serialWork(); 
} 

var s1 = stopwatch.ElapsedMilliseconds; 

// Run parallelizable batch of work in serial to get our baseline 
foreach (var notParallelWork in parallelizableWorkLoad) 
{ 
    notParallelWork(); 
} 

stopwatch.Stop(); 
var s2 = stopwatch.ElapsedMilliseconds - s1; 

An dieser Stelle haben wir, wie lange es jede Arbeitsbelastung in Serien laufen nahm. Lasst es uns jetzt erneut ausführen, wobei der parallelisierbare Teil parallelisiert ist.

stopwatch.Reset(); 
stopwatch.Start(); 
// Run Serial-only batch of work 
foreach (var serialWork in serialWorkLoad) 
{ 
    serialWork(); 
} 

var p1 = stopwatch.ElapsedMilliseconds; 

// Run parallelizable batch of work in with as many degrees of parallelism as we can 
Parallel.ForEach(parallelizableWorkLoad, (workToDo) => workToDo()); // In Java this is Magic Unicorns 

stopwatch.Stop(); 
var p2 = stopwatch.ElapsedMilliseconds - p1; 

Jetzt, wo wir die Grundlinie und die parallelisierte Version haben, können wir die Beschleunigung berechnen und unsere Ergebnisse berichten:

var speedup = (double)(s1 + s2)/(p1 + p2); 

Console.WriteLine("Serial took : {2}ms, {0}ms for serial work and {1}ms for parallelizable work", s1, s2, s1 + s2); 
Console.WriteLine("Parallel took: {2}ms, {0}ms for serial work and {1}ms for parallelizable work", p1, p2, p1 + p2); 
Console.WriteLine("Speedup was {0:F}x", speedup); 

Und wie Amdahl Gesetz Ihnen sagt, ist es schwer, sich perfekt mit den maßstabs Anzahl der Kerne, die Sie wegen der Nur-Serial-Arbeit haben.