c# - C# 中的阿姆达尔定律示例

标签 c# multithreading

我当时正在研究一些并行化,这让我开始研究阿姆达尔定律。我已经阅读了很多关于该主题的帖子;

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);
}

如您所见,为了好玩,我已经使可并行化的工作负载变得更重一些,并作为它的一个不错的例子。

接下来我们必须以串行方式运行两个工作负载以获得我们的基线:

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);

正如 Amdahl 定律告诉您的那样,由于仅串行工作,很难与您拥有的内核数量完美扩展。

关于c# - C# 中的阿姆达尔定律示例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14326211/

相关文章:

c# - 内存记录过多的 LINQ to SQL

从 pthread 内部调用函数?

cocoa - NSOperation 传递给委托(delegate)时导致崩溃

multithreading - WCF 中的 UnitOfWork 与 Quartz(线程)

multithreading - 您是否期望 future 的 CPU 代不会缓存一致?

c# - MVC SiteMap 从 menuhelper 中隐藏一个节点,但在 sitepathhelper 中显示(面包屑)

c# - 要显示的 Linq 表达式

java - 如何让一个线程等待并执行另一个???

c# - 将枚举映射到 json 属性

c# - 构建 C# 类的最佳方式