2012-11-27 35 views
1

我在我的代码中使用了parallel for循环来在大量实体(12,000)上运行长时间运行的进程。低效Parallel.For?

该进程解析一个字符串,通过一些输入文件(我已经读过,基于IO的线程的好处数量可能有问题,但它似乎已经加快了其他地方的速度)和输出一个匹配的结果。

最初,这个过程非常快 - 但最终会放慢抓取。有可能它只是遇到了一些特别棘手的输入数据,但这似乎不太可能更接近于事物。

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

然而,看看不匹配的ID的数量,它看起来像程序一次处理超过400个不同的实体。这看起来像是大量的IO,它可能是问题的根源。

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

  • 难道我解释了无与伦比的ID的正确,或者是有一些聪明的东西去的场面我的思念,或力挺明显的东西?
  • 如果您同意我发现的内容是正确的,那么我怎样才能限制它一次旋转的数量?

我意识到这可能是一个有点非正统的问题,因为没有代码,可能会很棘手,但任何帮助表示赞赏,如果有任何更多的信息,你想要让我知道在评论中。

+0

你可能是对的,但是,我们怎么知道你没有看到你在做什么。线程之间的争用在哪里? – Jodrell

回答

2

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

  • 无与伦比的标识指示我,正在处理该数据的线程被降低优先级。这可能是由于IO或线程池试图进行优化,但是看起来好像你是强烈的IO绑定那么这很可能是你的问题。
  • 我会看看Parallel.For,具体使用ParallelOptions.MaxDegreesOfParallelism将任务的最大数量限制在合理数量。我会建议通过试验和错误来确定最佳度数,从你拥有的处理器内核数量开始。

祝你好运!

+0

另外,你可以看看这个问题:[限制C#中并行线程的数量](http://stackoverflow.com/q/8853907/947171) –

+0

谢谢,请看看。无与伦比的数量让我意识到 - 我期待着看到我拥有的核心数量,看到这个数字似乎有点极端,因为我认为这是为了计算出最佳数字本身,我认为这个数字应该是你说过,pc上的核心数量还是存在的。 –

+3

对于IO界限任务,确定最大并行度时不应该担心核心数量;这只是一个问题,需要多少硬盘才能达到100%的吞吐量。这可能低至2(一个需要处理,另一个需要从磁盘中读取)。可能还有一些,但核心数量不应该相关(很多)。 – Servy

0

让我首先确认从硬盘驱动器同时读取2个文件是一个非常糟糕的想法(至少直到大多数HDs都有SSD),更不用说整个事情的数量是多少使用。 并行性的使用用于使用实际可并行化的资源(CPU功率)来优化处理。如果您从硬盘驱动器读取流程读取数据,那么您将失去大部分好处。即使这样,即使CPU功率也不容易无限平行化。一个普通的台式机CPU可以同时运行多达10个线程(显然取决于模型,但这是数量级)。

所以两件事

  • 首先,我要作你的实体使用的所有文件的假设,但你的文件不是太大而被加载到内存中。如果是这样的话,你应该将你的文件读入对象(即存入内存),然后使用这些对象来对你的实体进行并行处理。如果没有,你基本上依靠你的硬盘缓存来不重新读你的文件,每次你需要它们时,你的硬盘缓存远小于你的内存(1000倍)。

  • 第二,你不应该在12.000项目上运行Parallel.For。 Parallel.For实际上会(尝试)创建12.000个线程,并且实际上比10个线程更差,因为并行化会产生很大的开销,并且由于它不能运行得更多,所以CPU不会从中受益一次10个线程。

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

根据我的经验,使用任何并行应该总是被评估为不在实际中使用它,即通过实际分析您的应用程序。不要以为它会变得更好。

+0

事实上,正如我在问题中提到的那样,在处理文件时通常并不是很有益处,并且通过并行测试更快。虽然它会定期读取文件,但它对收到的内容进行了足够的处理,似乎是一种好处。 不幸的是,这些文件大部分都是太大而无法加载到内存中 - 一些文件总计大量的GB(这也是我无法控制的)。 我会看看AsParallel,谢谢。 Parallel.For尝试为每个项目创建一个线程是我的新闻我认为它创建了一个最佳的不。 –