【问题标题】:Multithreaded app in multicore environment - weird load per core多核环境中的多线程应用程序 - 每个内核的负载很奇怪
【发布时间】:2011-09-06 20:13:11
【问题描述】:

给定环境:16 核 Xeon 处理器,操作系统 - Win 2008 server R2。

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

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

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

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

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

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

所以我无法解释的主要趋势 - 更多线程意味着每个核心的平均负载更低,整体 CPU 使用率最高约为 20-25%。并且线程中的每个操作都随着线程数的增长而运行得更慢。

有什么想法可以解释这些奇怪的事情吗?

UPD

应用Server GC后画面发生了明显变化

16 核上的 8 个线程插图:

16 核上的 12 个线程插图:

16 核上的 15 个线程插图:

所以,看起来 CPU 使用率随着核心数量的增长而增加。 困扰我的第一件事是它看起来像所有内核都被使用并且线程从内核跳到内核,所以整体性能不是那么好。

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

可能的原因是什么?

【问题讨论】:

  • 只是为了确定...您使用的是服务器 GC 吗? stackoverflow.com/questions/5423951/c-gc-for-server 可能问题与GC有关。
  • 这是一个好主意,如果您还没有使用它。但是,我怀疑这是服务器 GC 问题,因为这往往会导致负载随时间变化,并且通常在内存消耗中可见 - 看起来该服务器仍然有 35GB 的可用内存,所以我怀疑 GC压力是(主要)问题......
  • @Reed 其他 GC 在收集时停止所有线程。而且它们消耗的 CPU 越多,线程数越多,因为它们需要自旋等待其他线程到达 GC 可以开始收集的点。发生了和我类似的事情stackoverflow.com/questions/4969963/…
  • 谢谢,Xanatos 您的信息和链接帮助解决了这个问题。服务器 GC 极大地提升了性能 :) 现在它似乎更具可扩展性。
  • 哎呀,性能确实提高了,但可伸缩性仍然不存在。

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


【解决方案1】:

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

【讨论】:

  • 我同意克里斯的观点。您描述的行为与等待某些(磁盘/网络)IO 功能完成时阻塞的 CPU 线程高度一致。
【解决方案2】:

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

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

解决此问题的方法是使用Partitioner class 将您的工作项预先划分为块,然后并行遍历项目的“块”。详情请见How to: Speed Up Small Loop Bodies

【讨论】:

  • 事实并非如此 - 每个单元的工作量很大,但是感谢有关分区器的重要信息,无论如何我都会使用它。
  • 主要要做的是从一堆帐户中为每个帐户进行大量计算。帐户被分区(现在通过 Partitioner 类;))成块,每个块都在自己的线程中处理。
  • @Roger:计算是纯数字的吗?您是否进行了分析以查看是否存在任何 IO 或网络争用?
  • 计算纯粹是数字,我必须找出但只要所有必需的附加数据都驻留在 RAM 中并且所有结果都存储在 RAM 中,就不应该命中任何 IO/网络。但由于某些未知原因,应用程序的扩展性很差。服务器 GC 提供了巨大的性能提升,但后来我发现 16 线程版本并不比 12 线程快。因此需要进一步调查。
  • @Roger:你分析过它了吗? VS 中的并发可视化工具以及良好的性能。应用程序可能会提供一些线索 - 特别是如果您查看并发可视化程序中的任何争用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-05-05
  • 1970-01-01
  • 2013-02-28
  • 2012-10-02
  • 2012-01-25
  • 1970-01-01
  • 2016-05-08
相关资源
最近更新 更多