Как именно работает AsParallel? - PullRequest
6 голосов
/ 28 ноября 2009

Это не подходит для приседа в следующей тестовой программе. Это потому, что я тестирую с небольшим списком?

static void Main(string[] args)
{
    List<int> list = 0.UpTo(4);

    Test(list.AsParallel());
    Test(list);
}

private static void Test(IEnumerable<int> input)
{
    var timer = new Stopwatch();
    timer.Start();
    var size = input.Count();
    if (input.Where(IsOdd).Count() != size / 2)
        throw new Exception("Failed to count the odds");

    timer.Stop();
    Console.WriteLine("Tested " + size + " numbers in " + timer.Elapsed.TotalSeconds + " seconds");
}

private static bool IsOdd(int n)
{
    Thread.Sleep(1000);
    return n%2 == 1;
}

Обе версии работают 4 секунды.

Ответы [ 3 ]

24 голосов
/ 28 ноября 2009

Task Parallel Library заботится о статическом типе последовательности. Должно быть IParallelEnumerable<T> для операций, которые должны обрабатываться TPL. Вы возвращаете коллекцию обратно на IEnumerable<T>, когда звоните Test. Поэтому компилятор будет разрешать .Where вызов последовательности в System.Linq.Enumerable.Where метод расширения вместо параллельной версии, предоставленной TPL.

5 голосов
/ 21 марта 2011

(Обновление для .NET4, поскольку этот вопрос занимает довольно высокое место в поиске Google для AsParallel ())

Всего несколько изменений позволят вашему примеру работать так, как вы ожидаете.

Изменить List<int> list = 0.UpTo(4); на var list = Enumerable.Range(0, 4);

Ваш пример сработает, если вы добавите перегрузку функции с подписью, которая принимает ParallelQuery ...

    private static void Test(ParallelQuery<int> input)
    {
        var timer = new Stopwatch();
        timer.Start();

        int size = input.Count();
        if (input.Where(IsOdd).Count() != size / 2)
        {
            throw new Exception("Failed to count the odds");
        }
        timer.Stop();

        Console.WriteLine("Tested " + size + " numbers in " + timer.Elapsed.TotalSeconds + " seconds");
    }

Либо вы можете использовать синтаксис LINQ ....

    private static void Test(ParallelQuery<int> list)
    {
        var timer = Stopwatch.StartNew();

        if ((from n in list.AsParallel()
             where IsOdd(n)
             select n).Count() != (list.Count() / 2))
        {
            throw new Exception("Failed to count the odds");
        }

        Console.WriteLine("Tested " + list.Count() + " numbers in " + timer.Elapsed.TotalSeconds + " seconds");
    }

Надеюсь, это кому-нибудь поможет!

2 голосов
/ 28 ноября 2009

Как работает Parallel, помещая ваши вещи в ThreadPool. Кроме того, сколько ядер у вас есть? Если вы работаете на одноядерном компьютере, запуск которого все равно займет около 4 секунд.

...