1

我在我的代码中使用并行 for 循环在大量实体(12,000)上运行长时间运行的进程。

该过程解析一个字符串,遍历许多输入文件(我已经读过,鉴于基于 IO 的事物的数量,线程的好处可能值得怀疑,但它似乎在其他地方加快了速度)并输出匹配的结果。

最初,该过程进行得非常快 - 但最终会慢到爬行。它可能只是遇到了一些特别棘手的输入数据,但这似乎不太可能仔细观察。

在循环中,我添加了一些调试代码,当它开始/结束迭代时打印“开始处理:”和“完成处理:”,然后编写了一个配对开始和结束的程序,最初是为了找到哪个 ID 是导致崩溃。

但是,从不匹配 ID 的数量来看,该程序似乎同时处理了超过 400 个不同的实体。这似乎是,对于大量的 IO,它可能是问题的根源。

所以我的问题是(是)这个(这些):

  • 我是否正确地解释了不匹配的 ID,或者在幕后我错过了一些聪明的东西,或者甚至是一些明显的东西?
  • 如果您同意我发现的内容是正确的,我该如何限制它分拆并立即执行的数量?

我意识到这可能是一个有点非正统的问题,并且由于没有代码,可能很难回答,但感谢您提供任何帮助,如果您想了解更多信息,请在评论中告诉我。

4

2 回答 2

2

没有看到一些代码,我可以猜测你的问题的答案:

  • 不匹配的 ID 向我表明正在处理该数据的线程正在被取消优先级。这可能是由于 IO 或线程池试图优化,但似乎如果您受到强烈的 IO 限制,那么这很可能是您的问题。
  • 我会看一下Parallel.For,特别是使用ParallelOptions.MaxDegreesOfParallelism将最大任务数限制为合理的数量。我建议从您拥有的处理器内核数量开始,通过反复试验来确定最佳度数。

祝你好运!

于 2012-11-27T16:39:45.890 回答
0

让我首先确认从硬盘驱动器同时读取 2 个文件确实是一个非常糟糕的主意(至少在大多数 HD 都是 SSD 之前),更不用说你的整个设备正在使用的数字了。并行性的使用有助于使用实际上可并行化的资源(即 CPU 能力)来优化处理。如果您从硬盘驱动器并行读取进程,那么您将失去大部分好处。

即便如此,即使是 CPU 能力也不容易发生无限并行化。一个普通的台式机 CPU 最多可以同时运行 10 个线程(显然取决于型号,但这是数量级)。

所以有两件事

  • 首先,我将假设您的实体使用您的所有文件,但您的文件不会太大而无法加载到内存中。如果是这种情况,您应该将文件读入对象(即读入内存),然后使用这些对象并行处理您的实体。如果没有,您基本上是在每次需要文件时都依赖硬盘驱动器的缓存而不是重新读取文件,并且硬盘驱动器的缓存远小于内存(1000 倍)。

  • 其次,您不应该在 12.000 个项目上运行 Parallel.For。Parallel.For 实际上会(尝试)创建 12.000 个线程,这实际上比 10 个线程更糟糕,因为并行化会产生很大的开销,而且你的 CPU 根本不会从中受益,因为它不能运行超过一次10个线程。

您可能应该使用更有效的方法,即IEnumerable<T>.AsParallel()扩展(.net 4.0 附带)。这将在运行时确定要运行的最佳线程数,然后将您的可枚举分成尽可能多的批次。基本上,它为你完成了这项工作——但它也会产生很大的开销,所以它只有在处理一个元素实际上对 CPU 来说成本很高时才有用。

根据我的经验,应该始终评估使用任何并行的东西,而不是在现实生活中不使用它,即通过实际分析您的应用程序。不要以为它会更好地工作。

于 2012-11-27T17:09:37.847 回答