我写了一些基本的示例代码来熟悉PLINQ.
我遇到了一些奇怪的东西.我不知道我的代码中是错误还是我对PLINQ的理解错误.
MSDN文档指出,添加AsOrdered()将以可能的性能成本保留调用的顺序.
我写了一些单元测试,并注意到文档中所述的对结果集的顺序的影响.但我已经看到了对性能的负面影响.
这是我的方法:
public IEnumerable<int> ParallelCalculatePrimesUpTo(int maxValue)
{
return from number in Enumerable.Range(1, maxValue).AsParallel()
where IsPrime(number)
select number;
}
public IEnumerable<int> OrderedParallelCalculatePrimesUpTo(int maxValue)
{
return from number in Enumerable.Range(1, maxValue).AsParallel().AsOrdered()
where IsPrime(number)
select number;
}
Run Code Online (Sandbox Code Playgroud)
而我非常简单的基准测试
[TestMethod]
public void SimplisticBenchmark6()
{
var primeNumberCalculator = new PrimeNumberCalculator();
var startTime = DateTime.Now;
primeNumberCalculator.ParallelCalculatePrimesUpTo(10000000).ToList();
var totalTime = DateTime.Now - startTime;
Console.WriteLine(totalTime);
}
[TestMethod]
public void SimplisticBenchmark7()
{
var primeNumberCalculator = new PrimeNumberCalculator();
var startTime = DateTime.Now;
primeNumberCalculator.OrderedParallelCalculatePrimesUpTo(10000000).ToList();
var totalTime = DateTime.Now - startTime;
Console.WriteLine(totalTime);
}
Run Code Online (Sandbox Code Playgroud)
无论我多久运行一次这个测试,有序版本都会打败无序版本.我的四核计算机上的订购速度大约快4秒.对于有序的一个,我得到大约18秒,对于无序的一个,我得到22秒.我在两天的时间内完成了几十次测试(在那些日子之间重新启动).
如果我降低数10 000 000 6 000 000,差异仍然存在,只是不显着,如果我它降低到3 000 000,它是关于相同的速度.
我尝试按执行顺序运行测试,结果是一样的.
以下是在PLINQ查询中调用的IsPrime方法:
// uses inneficient trial division algorithm
private bool IsPrime(int number)
{
if (number == 1)
return false;
for (int divisor = 2; divisor <= Math.Sqrt(number); divisor++)
{
if (number % divisor == 0)
return false;
}
return true;
}
Run Code Online (Sandbox Code Playgroud)
这解释了什么?
您能告诉我们 4 个不同核心的 CPU 利用率是多少吗?AsOrdered() 可能会强制在同一核心上发生更多顺序调用。随着局部性的改进,硅级缓存和分支预测可能对您有利。
另一种可能性是,.NET 框架在使用 AsOrdered() 投影时针对单调递增整数 (int.Range) 的情况进行了一些优化。我不确定这将如何运作,但这是可能的。
一个有趣的比较测试是按随机顺序生成第三组数字(显然,您必须提前将它们随机化,然后处理三个数组)。那你看看跟这个有没有关系?
| 归档时间: |
|
| 查看次数: |
1539 次 |
| 最近记录: |