【holm】并行Linq(PLinq)

PLinq

并行Linq(PLinq)是Linq模式的并行实现。PLinq查询类似普通的Linq查询,但它会将数据源分成片段,然后在多个处理器上对单独工作线程上的每个片段并行执行查询。

System.Linq.ParallelEnumerable 类公开了几乎所有的 PLINQ 功能。 它和 System.Linq 命名空间类型的其余部分一起被编译到 System.Core.dll 程序集中。 Visual Studio 中默认的 C# 和 Visual Basic 项目均会引用该程序集并导入该命名空间。

使用PLinq

针对任何一个Enumerable对象使用AsParallel()方法即可得到并行的查询。

    Array arr1 = Array.CreateInstance(typeof(int), 100);
    for (int i = 0; i < arr1.Length; i++)
    arr1.SetValue(i, i);
    var res1 = from int x in arr1.AsParallel() where x % 2 == 0 select x;

注意:AsParallel()是PLinq的入口点。

执行模式

PLinq在分析查询的总体结构之后会选择并行化查询或者顺序化查询。使用WithExecutionMode方法和System.Linq.ParallelExecutionMode枚举中的ForceParallelism字段强制并行化整个查询。

并行度

使用WithDegreeOfParallelism方法指示PLnq使用不超过指定数量的处理器。

var res2 = from x in arr1.AsParallel().WithDegreeOfParallelism(2)
            where x > 42
            select x;

保留源序列排序结果

  • AsOrdered方法指定PLinq应为查询的其余部分保留源序列的排序,或直到通过使用orderby子句更改排序为止。
  • AsUnordered指定保留源序列的排序不需要查询其余部分的PLinq。

注意:PLINQ 暂留查询其余部分的顺序强制施加运算符生成的序列顺序。 也就是说,OrderBy 和 ThenBy 等运算符被视为后跟 AsOrdered 调用。

使用ForAll遍历查询结果

var res1 = from int x in arr1.AsParallel() where x % 2 == 0 select x;
List<int> ls1 = new List<int>();
res1.ForAll((x) => ls1.Add(x));

类似于:

List<int> ls2 = new List<int>();
foreach(int item in res1)
{
    ls2.Add(item);
}

其中,

  • 使用foreach遍历有一个合并使用Linq时满足条件的select值输出的过程,ForAll则没有。
  • ForAll为并行遍历。foreach为顺序遍历。

以下是foreachForAll在查询执行方面的区别:
和在查询执行方面的区别

在 PLINQ 中,在必须保留查询结果的最终排序,以及以按串行方式处理结果时,例如当为每个元素调用 Console.WriteLine 时,则可以使用 foreach。 为了在无需顺序暂留以及可自行并行处理结果时更快地执行查询,请使用 ForAll 方法执行 PLINQ 查询。 ForAll 不执行最终的这一合并步骤。

可取消PLinq查询

PLINQ 在 .NET Framework 4 中与取消类型集成在一起。因此,与顺序 LINQ to Objects 查询不同,可以取消 PLINQ 查询。 若要创建可取消 PLINQ 查询,请在查询中使用 WithCancellation 运算符,并提供 CancellationToken 实例作为参数。 如果令牌上的 IsCancellationRequested 属性设置为 true,PLINQ 就会注意到它,停止处理所有线程并抛出 OperationCanceledException。

指路:

自定义分区程序

指路官方文档(提前挖坑)

性能

在很多情况下,可以并行化查询,但是设置并行查询的开销可能会超出获得的性能收益。 如果查询不执行大量的计算,或者如果数据源较小,则 PLINQ 查询的速度可能比顺序 LINQ to Objects 查询的速度慢。

参考资料

原文地址:https://www.cnblogs.com/holm/p/12856869.html