データを分割し、複数のプロセッサでクエリを並列実行 (execute in parallel) させられます。
メソッド | 機能 |
---|---|
AsParallel(IEnumerable) | クエリの並列化 (parallelization) を有効にする |
AsSequential<TSource>(ParallelQuery<TSource>) | ParallelQuery<TSource>をIEnumerable<T>へ変換し、クエリを順に評価することを強制する |
AsOrdered(ParallelQuery) | データソースの処理を、順序ありとできる |
WithExecutionMode<TSource>(ParallelQuery<TSource>, ParallelExecutionMode) | クエリの実行モードを設定できる |
クエリの実行モードを設定できます。そのとき並列に実行することを強制することで、クエリの構造と無関係に並列化できます。
public static System.Linq.ParallelQuery<TSource> WithExecutionMode<TSource> ( this System.Linq.ParallelQuery<TSource> source, System.Linq.ParallelExecutionMode executionMode );ParallelEnumerable.WithExecutionMode<TSource> メソッド (System.Linq) | Microsoft Learn
IEnumerable<int> source = Enumerable.Range(0, 10); Func<int, bool> selector = (num) => { Task.Delay(100).Wait(); return num % 2 == 0; }; IEnumerable<int> query1 = // LINQ from num in source where selector(num) select num; ParallelQuery<int> query2 = // PLINQ from num in source.AsParallel() where selector(num) select num; ParallelQuery<int> query3 = // PLINQ 並列を強制 from num in source.AsParallel().WithExecutionMode(ParallelExecutionMode.ForceParallelism) where selector(num) select num; int r1 = query1.Count(); // 約1100 ms int r2 = query2.Count(); // 約1100 ms int r3 = query3.Count(); // 約220 ms int r4 = query1.Count(); // 約1100 ms int r5 = query2.Count(); // 約220 ms
PLINQでは並列に実行されることで、既定では順序が維持されません。これを維持するように指示できます。
public static System.Linq.ParallelQuery<TSource> AsOrdered<TSource> ( this System.Linq.ParallelQuery<TSource> source );AsOrdered<TSource>(ParallelQuery<TSource>) - ParallelEnumerable.AsOrdered メソッド (System.Linq) | Microsoft Learn
順序の維持が不要となったら、AsUnordered<TSource>()を呼び出しそれを無効にします。
orderbyなどで並べ替えると、AsUnordered<TSource>()が呼び出されるまで順序が維持されます。Query Operators and Ordering - Order Preservation in PLINQ - .NET | Microsoft Learn
IEnumerable<int> source = Enumerable.Range(0, 10); Func<int, bool> selector = (num) => { Task.Delay(1).Wait(); return num % 2 == 0; }; IEnumerable<int> query1 = // LINQ from num in source where selector(num) select num; ParallelQuery<int> query2 = // PLINQ from num in source.AsParallel() where selector(num) select num; ParallelQuery<int> query3 = // PLINQ AsOrdered()指定 from num in source.AsParallel().AsOrdered() where selector(num) select num; ParallelQuery<int> query4 = // PLINQ orderbyで並べ替え from num in source.AsParallel() where selector(num) orderby num select num; int[] a1 = query1.ToArray(); // 0, 2, 4, 6, 8 int[] a2 = query2.ToArray(); // 0, 8, 2, 4, 6 int[] a3 = query3.ToArray(); // 0, 2, 4, 6, 8 int[] a4 = query4.ToArray(); // 0, 2, 4, 6, 8