【问题标题】:C# Efficiently Dividing Tasks Between CoresC# 在内核之间高效地划分任务
【发布时间】:2010-08-20 15:49:50
【问题描述】:

我正在做一个在我的 8 核工作站上运行的小型模拟。模拟涉及对大量独立节点之间的交互进行建模。在一个阶段,我需要对每个节点并行执行一系列简单的原子操作。我一直在使用 System.Threading.Tasks 中的 Parallel.ForEach 将操作同时应用于所有节点列表中的每个节点。

这适用于我用于测试的 100-500 个节点。负载平衡得很好,所有内核都在不断使用。不幸的是,当我尝试使用主数据集(5000 多个节点)运行模拟时,一切都出错了。所有 8 个内核大部分时间都处于空闲状态,每隔几秒就会达到 100%,然后又恢复到 1% 的利用率。几分钟后,抛出 OutOfMemoryException 并且程序崩溃。

我不完全确定出了什么问题,但我仍然怀疑我当前的代码产生的线程数比该任务的最佳线程数要多得多。我认为理想的方法是让模型检测可用内核的数量 N,将节点列表划分为 N 个段,然后生成 N 个线程,给每个线程一个单独的列表分区。

我想问的是,如果这确实是解决问题的好方法,是否存在更好的解决方案,以及它应该如何在 C# 中实现?欢迎任何建议或cmets。

编辑:按要求编写代码示例

Parallel.ForEach(listOfNodes, tempNode =>
{
   tempNode.foo();
} );

<snip>

void foo()
{
   foreach(myType bar in listOfmyType)
   {
       if (bar.isActive)
           setNodeActive();
   }
} 

【问题讨论】:

  • 演示问题的简短但完整的代码示例会有所帮助,否则您可能得到的只是猜测。
  • 您的内存不足;如果你修改交换文件,CPU 利用率会急剧下降,因为 CPU 大部分时间都在等待磁盘。因此可以解释您机器的行为;补救措施是减少内存使用量。
  • LBushkin,我想过这个问题,但是代码太通用了,似乎没有什么帮助。只是:Parallel.ForEach(listOfNodes, tempnode => { tempnode.foo() });
  • tempnode.foo() 看起来像什么?如果您使用普通的 foreach,您是否仍然会出现内存不足错误(显然它将只使用一个核心......)但它可能指向foo() 中的问题
  • 只是一种预感,但是由于您正在对交互进行建模,您是否有任何增长 O(N^2) 的数据结构?由于与每个节点的数据相关的开销,您可能比您想象的更快地耗尽内存。

标签: c# .net multithreading parallel-processing


【解决方案1】:

请参阅此线程,其中讨论了限制 Parallel.For 用于避免内存不足的线程数:

http://connect.microsoft.com/VisualStudio/feedback/details/534571/parallel-foreach-may-create-an-inordinate-number-of-threads

我会尝试将 ParallelOptions.MaxDegreeOfParallelism 设置为 500 左右,看看会发生什么。

【讨论】:

  • 500 似乎仍然很高,你能解释一下吗?我的估计是 10-20(8 个内核,很少或没有 I/O)。
  • 是的,我认为 8 或 10 会是一个很好的限制。为什么 500 是一个很好的起始估计值?
  • 因为你说它在 500 个节点上运行良好。它不一定是 500。我有一个 Windows 服务,它在网站后面的后台执行长时间运行的任务。它使用ThreadPool 对象。我对其进行了一些测试,发现理想的同时执行线程数是机器中的内核数,即 YMMV。
  • 啊,有道理。谢谢!
  • 是的,对于纯 CPU 密集型系统来说,理想的情况是运行 N 个线程 (N = #cores)。但是您需要一些空间来补偿等待(I/O 或锁)线程。所以8+是你的起点。别忘了,1 个线程 = 1 MB
【解决方案2】:

我认为理想的方法是 模型检测数量 可用核数 N,对列表进行分区 将节点分成 N 段,然后产生 N 线程,给每个线程一个单独的 列表的分区。

这正是Parallel.ForEach所做的,所以肯定还有另一个问题。

你自己很难想出一个更好的(线程管理)系统。但是您可以在任务库中使用自定义调度程序。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-05-19
    • 1970-01-01
    • 2016-06-02
    • 2011-02-14
    • 2015-08-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多