3

我正在解决一个需要执行许多令人尴尬的可并行化任务的问题。该任务是通过从数据库中读取数据来创建的,但是所有任务的集合将超过机器上的内存量,因此必须创建、处理和处置任务。我想知道解决这个问题的好方法是什么?我正在考虑以下两种方法:

  1. 实现一个同步的任务队列。实现一个生产者(任务创建者),它从数据库中读取数据并将任务放入队列中(将队列中当前的任务数量限制为一个恒定值,以确保不超过内存量)。有多个消费者进程(任务处理器)从队列中读取任务、处理任务、存储结果并处理任务。在这种方法中,大量的消费者进程会是多少?

  2. 使用 .NET 并行扩展(PLINQ 或并行),但我知道必须创建一个任务集合(我们可以在并行处理的同时将任务添加到集合中吗?)。所以我们将创建一批任务——说一次 N 个任务,然后处理这批任务并读取另外 N 个任务。

您对这两种方法有何看法?

4

6 回答 6

4

使用有界队列的 ThreadPool 以避免使系统不堪重负。

如果您的每个工作任务都受 CPU 限制,那么最初配置您的系统,使系统中的线程数等于您的机器可以运行的硬件线程数。

如果您的任务不受 CPU 限制,那么您将不得不试验池大小以获得适合您特定情况的最佳解决方案

您可能必须尝试使用​​任何一种方法来获得最佳配置。

基本上,测试、调整、测试、重复,直到你满意为止。

于 2009-05-07T15:09:32.387 回答
3

我没有机会实际使用 PLINQ,但我知道 PLINQ(如 vanilla LINQ)是基于 IEnumerable 的。因此,我认为这可能是通过 C# 迭代器块(即 yield 关键字)实现任务生产者的情况。

假设您没有执行任何必须提前知道整个任务集的操作(例如排序),我希望 PLINQ 只会消耗它一次可以处理的尽可能多的任务。此外,本文还引用了一些策略来控制 PLINQ 如何使用输入(标题为“处理查询输出”的部分)。

编辑:将 PLINQ 与 ThreadPool 进行比较。

根据这篇 MSDN 文章,有效地将工作分配给线程池并非易事,即使您“正确”地进行操作,使用 TPL 通常也会表现出更好的性能。

于 2009-05-07T15:19:02.707 回答
2

使用线程池

然后,您可以将所有内容排队,并且项目将在线程变得可用于池时运行,而不会压倒系统。唯一的技巧是确定一次运行的最佳线程数。

于 2009-05-07T15:03:01.467 回答
1

听起来像是 Microsoft HPC Server 2008 的工作。鉴于任务的数量是压倒性的,您需要某种并行进程管理器。这就是 HPC 服务器的全部意义所在。

http://www.microsoft.com/hpc/en/us/default.aspx

于 2009-05-07T15:02:05.213 回答
0

为了给出一个好的答案,我们需要回答几个问题。

每个单独的任务是否可并行化?还是每个任务都是可并行化主任务的产物?

另外,是任务的数量会导致系统内存不足,还是每个任务持有和处理的数据量会导致系统内存不足?

于 2009-05-07T15:55:38.703 回答
-1

听起来Windows Workflow Foundation (WF) 可能是用于执行此操作的好东西。它还可能为您带来一些额外的好处,例如暂停/恢复您的任务。

于 2009-05-07T19:15:41.563 回答