我当时正处于某种瘫痪状态,这使我开始研究阿姆达尔定律。我已经阅读了许多有关该主题的文章;

Calculate performance gains using Amdahl's Law

How to calculate Amadahl's Law for threading effectiveness

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

...但是希望找到一个在实践中展示它的C#示例。搜索没有结果。从理论上讲,应该有可能进行串行应用程序,对可并行化部件进行计时,运行并行化版本,记录并行部件所需的长度,并将差异(知道正在使用多少个处理器)与Amdahl函数的结果进行比较。这是正确的吗,有人知道这样的例子吗?

最佳答案

注意:可以在My Github Page上找到该程序的完整的可下载版本。

因此,根据阿姆达尔定律,我们将工作分为“必须串行运行的工作”和“可以并行化的工作”,因此让我们将这两个工作负载表示为List<Action>:

var serialWorkLoad = new List<Action> { DoHeavyWork, DoHeavyWork };
var parallelizableWorkLoad = new List<Action> { DoHeavyWork, DoHeavyWork, DoHeavyWork, DoHeavyWork, DoHeavyWork, DoHeavyWork, DoHeavyWork, DoHeavyWork };
DoHeavyWork委托(delegate)出色地抽象为:
static void DoHeavyWork()
{
    Thread.Sleep(500);
}

如您所见,我为使可并行化的工作负载变得更加繁琐,并使其成为一个不错的例子。

接下来,我们必须在Serial中运行两个工作负载以获取基准:
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;

此时,我们需要花费多长时间才能串行运行每个工作负载。现在,让我们并行化可并行化部分,再次运行它。
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;

现在我们有了基准和并行化版本,我们可以计算加速并报告我们的发现:
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);

正如阿姆达尔定律告诉您的那样,由于仅串行工作,很难用您拥有的内核数来完美缩放。

07-24 19:31