为什么PLINQ只使用两个线程?

说我有一个IO绑定任务。 我使用WithDegreeOfParallelism = 10和WithExecution = ForceParallelism模式,但查询仍然只使用两个线程。 为什么?

我知道PLINQ通常会选择一个与我的核心数相等的并行度,但为什么它忽略了我对更高并行性的特定要求呢?

static void Main(string[] args) { TestParallel(0.UpTo(8)); } private static void TestParallel(IEnumerable 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; } 

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

此外,对于基于IO的操作,任何额外的线程都可能只是阻塞执行的第一个IO操作。

10是最大值

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

从这里:

MSDN

似乎PLINQ调整了线程数。 当我在一个while(true)循环中包装上面的代码时,前两次迭代需要两秒钟才能运行,但第三次及以上只需要一秒钟。 PLINQ了解核心是空闲的并且增加了线程数量。 令人印象深刻!

我同意Rory,除了IO。 没有使用磁盘IO进行测试,但是网络IO最终可能比更multithreading更有效,而不是CPU上的核心。

简单的测试(对于每个线程计数运行测试会更正确,因为网络速度不是常数,但仍然是)以certificate:

  [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线程。