Почему мой запрос AsOrdered PLINQ быстрее, чем мой неупорядоченный запрос

Я написал базовый пример кода, чтобы ознакомиться с 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;
}

Чем это объясняется?

6
задан Gilles 6 June 2012 в 00:40
поделиться