多核环境中的多线程应用程序 - 每个核心的奇怪负载

时间:2011-09-06 20:13:11

标签: .net multithreading .net-4.0 multicore task-parallel-library

给定环境:具有16个核心的Xeon处理器,OS - Win 2008服务器R2。

给定应用程序(.Net / C#)之前,并行负载1核心几乎100%。 获得一些利润的明显解决方案是使用.Net 4并行任务库来加速应用程序X次。 假设并行的应用程序部分非常合适 - 线程之间不会发生锁定(没有共享资源,每个并行任务完全独立)。 但令我遗憾的是,利润非常低 - 16线程应用大约工作。比顺序快2倍。

这是第一个插图--16个核心上的16个线程

16 http://s57.radikal.ru/i157/1109/48/e1df69e34c43.jpg

看起来很奇怪 - 每项任务都是相同的,但前8个核心的负载几乎相同(~30%),其他8个核心的负载逐渐下降。

所以,我尝试了不同的配置,例如16核上的8个线程

8 http://s45.radikal.ru/i109/1109/be/148f110a973d.jpg

看起来8个线程都在8个核心上运行,并且线程没有从一个核心转移到另一个核心。此外,在8核上平均核心负载大于16核。

我通过分析器进行了一些研究 - 每个线程在单线程情况下具有相同的行为,就不同方法花费的时间百分比而言。只有(和平均)差异是绝对时间 - 随着线程数的增长而变得越来越大(就好像每个核心的性能都在下降)

所以我不能解释的主要趋势 - 更多线程意味着每个核心的平均负载更低,整数CPU使用率最多约为20-25%。随着线程数量的增加,线程中的每个操作都会运行得更慢。

有什么想法来解释这个奇怪的事情吗?

UPD

应用Server GC后,图片发生了显着变化

16核上的8个线程插图:

8AfterServerGC http://s004.radikal.ru/i207/1109/e8/94d0ce0e97f3.bmp

16核上的12个线程插图:

12AfterServerGC http://i025.radikal.ru/1109/9f/694544cf992e.bmp

16核上的15个线程插图:

15AfterServerGC http://i003.radikal.ru/1109/b2/82033ad2eadf.bmp

因此,随着核心数量的增长,cpu的使用量也在增加。 令我困扰的第一件事是,我看起来使用了所有核心,并且线程从核心跳到核心,所以整体性能不是那么好。

第二件事是应用程序最大速度为12个核心,15个核心给出相同的结果,16个核心甚至更慢。

可能的原因是什么?

2 个答案:

答案 0 :(得分:2)

您看到的模式通常表明存在I / O瓶颈。如果您的磁盘或网络正在运行完全为这些计算提供数据(或处理结果),那么您可以在一百万个核心上运行它而没有额外的好处。我建议使用Sysinternals Process Explorer来检查网络和磁盘I / O,看看是否存在问题,然后再尝试进一步了解为什么这不能很好地并行化。

答案 1 :(得分:1)

由于您的方法听起来没有内部同步,因此问题可能在分区中。

鉴于您正在使用TPL,必须根据分区程序将工作发送到核心。但是,实际的源IEnumerable<T>不是线程安全的,因此需要通过单个内核进行访问。实际上,如果实际工作量与项目数相比较小,这通常会导致性能特征,如上图所示。

解决这个问题的方法是使用Partitioner class将工作项预分区为块,然后并行遍历项目的“块”。有关详细信息,请参阅How to: Speed Up Small Loop Bodies