Я написал базовый пример кода, чтобы ознакомиться с 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;
}
И мои очень простые бенчмарки
[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);
}
Независимо от того, как часто я запускаю этот тест, упорядоченная версия превосходит неупорядоченную. Я получаю примерно на 4 секунды быстрее для заказанного на моем четырехъядерном компьютере. Я получаю около 18 секунд для заказанного и 22 секунды для неупорядоченного. Я запускал тесты десятки раз в течение двух дней (с перезагрузками между этими днями).
Если я уменьшу число с 10 000 000 до 6 000 000, разница все еще есть, но менее заметна, а если я уменьшу до 3 000 000, то скорость будет примерно такой же.
Я пробовал запускать тесты в обоих порядках выполнения, и результаты были одинаковыми.
Вот метод IsPrime, который вызывается в запросе PLINQ:
// 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;
}
Чем это объясняется?