PLINQ 真的不保持顺序吗?
Does PLINQ really not preserve order?
在 MSDN 据说 PLINQ 不保留顺序。我想在我的项目中演示它,但我有一个问题,那就是始终保持秩序。我有一个集合 List<Tuple<int, int>> table
,这些是我的查询:
var linqQuery = table
.Where(n => Enumerable.Range(2, (int) Math.Sqrt(n.Item1)).All(i => n.Item1 % i > 0))
.Take(10)
.ToList();
var plinqQuery = table
.AsParallel()
.Where(n => Enumerable.Range(2, (int) Math.Sqrt(n.Item1)).All(i => n.Item1 % i > 0))
.Take(10)
.ToList();
即使我不使用 .AsOrdered()
,它们也会产生相同的有序结果。谁能告诉我为什么?
PLINQ 不保证项目将按顺序处理。它是否按顺序处理它们取决于几个因素。
首先,事先并不知道这些操作将在多少个线程中执行。在小例子中,很可能只使用一个或两个线程。
其次,请记住 Task
不等于线程。任务就是做什么。线程是 运行 的引擎。任务管理器选择将哪个任务放到哪个线程上。它不会 运行 一个新线程只是因为有任务在等待,除非有未使用的 CPU 资源真正 运行 该线程。
第三,即使有多个线程运行并行执行任务,任务完成的顺序也可能与它们开始时的顺序相同。
结论是 PLINQ 不会做任何事情来使任务 运行 按照它们初始化的相同顺序执行,真正的执行顺序是几个因素的结果。您的代码不应依赖于任何一个结果。
如果您只是想展示它,为什么不使用带有大型 Enumerable 集的简单 ForEach 与 ForAll?
例如:
using System;
using System.Linq;
namespace SO.MacakM.Answer
{
class Program
{
static void Main(string[] args)
{
var range = Enumerable.Range(1, 1000);
Console.WriteLine("Using LINQ...");
range.ToList().ForEach(i => Console.WriteLine(i));
Console.WriteLine("Using PLINQ...");
range.AsParallel().ForAll(i => Console.WriteLine(i));
Console.Read();
}
}
}
你可能会把顺序打乱在最后一个。 Test it in .NET Fiddle
考虑使用
.AsOrdered()
示例:
list.AsParallel().AsOrdered()
请注意,这会影响性能
在 MSDN 据说 PLINQ 不保留顺序。我想在我的项目中演示它,但我有一个问题,那就是始终保持秩序。我有一个集合 List<Tuple<int, int>> table
,这些是我的查询:
var linqQuery = table
.Where(n => Enumerable.Range(2, (int) Math.Sqrt(n.Item1)).All(i => n.Item1 % i > 0))
.Take(10)
.ToList();
var plinqQuery = table
.AsParallel()
.Where(n => Enumerable.Range(2, (int) Math.Sqrt(n.Item1)).All(i => n.Item1 % i > 0))
.Take(10)
.ToList();
即使我不使用 .AsOrdered()
,它们也会产生相同的有序结果。谁能告诉我为什么?
PLINQ 不保证项目将按顺序处理。它是否按顺序处理它们取决于几个因素。
首先,事先并不知道这些操作将在多少个线程中执行。在小例子中,很可能只使用一个或两个线程。
其次,请记住 Task
不等于线程。任务就是做什么。线程是 运行 的引擎。任务管理器选择将哪个任务放到哪个线程上。它不会 运行 一个新线程只是因为有任务在等待,除非有未使用的 CPU 资源真正 运行 该线程。
第三,即使有多个线程运行并行执行任务,任务完成的顺序也可能与它们开始时的顺序相同。
结论是 PLINQ 不会做任何事情来使任务 运行 按照它们初始化的相同顺序执行,真正的执行顺序是几个因素的结果。您的代码不应依赖于任何一个结果。
如果您只是想展示它,为什么不使用带有大型 Enumerable 集的简单 ForEach 与 ForAll?
例如:
using System;
using System.Linq;
namespace SO.MacakM.Answer
{
class Program
{
static void Main(string[] args)
{
var range = Enumerable.Range(1, 1000);
Console.WriteLine("Using LINQ...");
range.ToList().ForEach(i => Console.WriteLine(i));
Console.WriteLine("Using PLINQ...");
range.AsParallel().ForAll(i => Console.WriteLine(i));
Console.Read();
}
}
}
你可能会把顺序打乱在最后一个。 Test it in .NET Fiddle
考虑使用
.AsOrdered()
示例:
list.AsParallel().AsOrdered()
请注意,这会影响性能