PLINQ延迟执行

5

我正在尝试理解如何使用PLINQ实现并行计算,考虑到延迟执行的情况。以下是一个简单的示例。

string[] words = { "believe", "receipt", "relief", "field" };
bool result = words.AsParallel().Any(w => w.Contains("ei"));

使用LINQ,我期望执行到“receipt”值时返回true,而不需要执行其余值的查询。

如果我们以并行方式执行此操作,“relief”的评估可能已经开始,而“receipt”的结果尚未返回。但是一旦查询知道“receipt”将导致true结果,其他线程会立即停止吗?

在我的情况下,这很重要,因为“any”测试可能非常昂贵,我希望释放处理器以执行其他任务。

1个回答

5

不幸的是,其他线程不会立即“yield”。

一旦 Any() 找到一个有效元素,PLINQ 调度程序将停止调度新线程来检查新元素。任何现有的分区器也将收到取消请求,这将防止这些分区对另一个项调用 Any()

然而,当前在您的 Any() 方法中执行 lambda 表达式的任何线程仍将继续执行,因为它们无法知道另一个线程已成功。它将阻止新线程调用 Any(),但不会取消所有“非常昂贵”的委托中的线程。

顺便说一下:

与 LINQ to Objects 不同,PLINQ 实际上并不使用延迟执行。当您在 IEnumerable<T> 上调用 AsParallel() 时,生成的 ParallelQuery<T> 实际上会以并行方式开始处理您的例程。延迟执行会大大降低 PLINQ 的效率,因为在事先创建工作分区器和调度之前,不可能并行调度。


编辑:

经过思考 - 如果您的 lambda 非常昂贵,您可能需要考虑使用 CancellationToken。我详细介绍了关于 PLINQ 中取消的工作原理。通常,您只需要使用一个令牌并调用 ThrowIfCancellationRequested() 即可 - 但是,您还可以使用 CancellationToken 并检查 IsCancellationRequested,这将使您的 lambda “提前退出”,为您提供更早停止后台处理的方法...


2
http://msdn.microsoft.com/en-us/library/dd997425(VS.100).aspx说延迟执行原则在PLINQ中仍然适用...您能否澄清一下您的副点是什么意思? - tbischel
2
@tbischel:它们有,也有不同...那条评论有点误导性。不同之处在于,在LINQ中,每个元素仅在请求时执行(延迟)。在PLINQ中,一旦进行第一个请求,就会设置Partitioner<T>,它开始将你的工作安排给多个线程。最终累计结果直到被请求之前都不会返回,但是处理会在请求元素之前发生。(如果您请求结果的元素1,则元素1、2、3和4可能都会被调度,并立即开始"工作"...) - Reed Copsey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接