你的“问题”是使用PLINQ时,它没有任何意义
PLINQ不会总是更快。 PLINQ将永远增加开销。
就CPU指令而言;无论您需要做多少工作(称之为X),您最终都会执行超过X条指令。 PLINQ将开展大量额外的工作,将工作委托给他们,并将结果返回到您可以使用的表单中。
这样做的好处是你可以有多个CPU/Core的工作。有时它会更快。当你所做的CPU工作量相对于开销很小时,它会变慢。
当我运行代码,我得到以下的输出:
顺序执行2毫秒
并行执行40毫秒
我还可以看到正在创建工作线程由PLINQ代码。这8个线程代表了2毫秒计算量的大量开销。通过两次运行“并行执行”基准测试,您可以感觉到它有多少开销。工作线程将会四处流动。这是我的输出与运行它的第二时间:
顺序执行2毫秒
并行#1执行40毫秒
并行#2执行3毫秒
第二时间是快多了;但仍然比不做任何事情慢。因为即使已经创建了工作线程 - PLINQ仍然需要做工作来分割线程之间的操作并以可以访问的格式重新获得结果。
您需要做的工作越多,对开销的影响就越小。在这个例子中,我用一个名为IsValid
的静态函数替换了你的Where lambda,并且我计算了%2 500次而不是一次。
static bool IsValid(int input)
{
int result=0;
for(int i =0;i<500;i++)
result = input%2;
return result == 0;
}
现在 - 我的执行时间是:
顺序执行36毫秒
并行#1执行47毫秒
并行#2执行9毫秒
你可以看到PLINQ仍然很慢第一次执行 - 但在第二次执行时速度明显加快。如果通过将环路从500增加到5000(在我的机器上)来实现CPU工作,PLINQ将胜出,而不用担心。
TL; DR - 你做得对;你只是没有做足够的工作来让PLINQ成为更快的选择。
下面是我做了什么,整个源代码:
static void Main(string[] args)
{
Stopwatch sw = new Stopwatch();
int[] vals = Enumerable.Range(0, Int16.MaxValue).ToArray();
sw.Start();
int[] x1 = vals.Where(IsValid).ToArray();
sw.Stop();
Console.WriteLine("Sequential Execution {0} milliseconds", sw.ElapsedMilliseconds);
sw.Restart();
int[] x2 = vals.AsParallel().Where(IsValid).ToArray();
sw.Stop();
Console.WriteLine("Parallel #1 Execution {0} milliseconds", sw.ElapsedMilliseconds);
sw.Restart();
int[] x3 = vals.AsParallel().Where(IsValid).ToArray();
sw.Stop();
Console.WriteLine("Parallel #2 Execution {0} milliseconds", sw.ElapsedMilliseconds);
Console.Read();
}
static bool IsValid(int input)
{
int result=0;
for(int i =0;i<5000;i++)
result = input%2;
return result == 0;
}
http://stackoverflow.com/questions/7582591/how-to-plinq-an-existing-linq-query-with-加入(阅读我的推荐读物)。简而言之:你的模操作太微不足道了。你需要更复杂的操作。 –