7

假设我有一个 IO-bound 任务。我正在使用 WithDegreeOfParallelism = 10 和 WithExecution = ForceParallelism 模式,但查询仍然只使用两个线程。为什么?

我知道 PLINQ 通常会选择与我的核心数量相等的并行度,但为什么它忽略了我对更高并行度的具体要求?

static void Main(string[] args)
{
    TestParallel(0.UpTo(8));
}

private static void TestParallel(IEnumerable<int> input)
{
    var timer = new Stopwatch();
    timer.Start();
    var size = input.Count();

    if (input.AsParallel().
        WithDegreeOfParallelism(10).
        WithExecutionMode(ParallelExecutionMode.ForceParallelism).
        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 回答 4

10

PLINQ 尝试找到最佳线程数以尽快执行您希望它执行的操作,如果您的 cpu 上只有 2 个内核,那么这个数字很可能是 2。如果您有一个四核,您会更多可能会出现 4 个线程,但在双核机器上创建 4 个线程并不能真正提高性能,因为只能同时激活 2 个线程。

此外,对于基于 IO 的操作,任何额外的线程都可能会简单地阻塞在执行的第一个 IO 操作上。

于 2009-11-28T14:45:28.873 回答
4

10 是最大值

设置要在查询中使用的并行度。并行度是将用于处理查询的并发执行任务的最大数量。

从这里:

MSDN

于 2009-11-28T14:55:01.960 回答
2

PLINQ 似乎调整了线程数。当我将上面的代码包装在一个 while(true) 循环中时,前两次迭代需要两秒钟才能运行,但第三次及以上只需要一秒钟。PLINQ 了解内核处于空闲状态并增加了线程数。感人的!

于 2009-11-28T19:45:43.777 回答
0

我会同意 Rory,除了 IO。尚未使用磁盘 IO 进行测试,但网络 IO 绝对可能对更多线程更有效,而不是 CPU 上的内核。

简单的测试(对每个线程计数多次运行测试会更正确,因为网络速度不是恒定的,但仍然如此)来证明:

    [Test]
    public void TestDownloadThreadsImpactToSpeed()
    {
        var sampleImages = Enumerable.Range(0, 100)
            .Select(x => "url to some quite large file from good server which does not have anti DSS stuff.")
            .ToArray();            

        for (int i = 0; i < 8; i++)
        {
            var start = DateTime.Now;
            var threadCount = (int)Math.Pow(2, i);
            Parallel.For(0, sampleImages.Length - 1, new ParallelOptions {MaxDegreeOfParallelism = threadCount},
                         index =>
                             {
                                 using (var webClient = new WebClient())
                                 {
                                     webClient.DownloadFile(sampleImages[index],
                                                            string.Format(@"c:\test\{0}", index));
                                 }
                             });

            Console.WriteLine("Number of threads: {0}, Seconds: {1}", threadCount, (DateTime.Now - start).TotalSeconds);
        }
    }

使用带有 SSD 的 8 核机器的 CDN 中的 500x500px 图像的结果是:

线程数:1,秒:25.3904522
线程数:2,秒:10.8986233
线程数:4,秒:9.9325681
线程数:8,秒:3.7352137
线程数:16,秒:3.3071892
线程数:32 ,秒:3.1421797
线程数:64,秒:3.1161782
线程数:128,秒:3.7272132

我认为最后一个结果有这样的时间,因为我们只需要下载 100 张图片:)

使用 8-64 线程的时间差异并不大,但那是在 8 核机器上。如果是 2 核机器(廉价的最终用户笔记本),我认为强制使用 8 线程会比 8 核机器强制使用 64 线程产生更大的影响。

于 2012-06-21T12:49:48.920 回答