7

对于下面的测试程序,它似乎没有做深蹲。这是因为我正在用一个小列表进行测试吗?

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 秒才能运行。

4

3 回答 3

24

任务并行库关心序列的静态类型。应该IParallelEnumerable<T>由 TPL 处理操作。IEnumerable<T>当您调用时,您正在将集合转换回Test。因此,编译器将解析.Where对序列System.Linq.Enumerable.Where扩展方法的调用,而不是 TPL 提供的并行版本。

于 2009-11-28T14:28:37.240 回答
5

(更新 .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");
    }

希望这对某人有帮助!

于 2011-03-21T19:52:38.507 回答
2

由于 Parallel 通过将您的东西放入 ThreadPool 来工作。另外,你有多少个核心?如果您正在使用单核机器,仍然需要大约 4 秒才能运行。

于 2009-11-28T14:32:09.040 回答