【发布时间】: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