说我有一个IO绑定任务。我使用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;
}
答案 0 :(得分:9)
PLINQ尝试找到最佳线程数,以便尽快执行您希望它执行的操作,如果您的cpu上只有2个内核,那么这个数字很可能是2.如果您有四核,那么将更有可能看到4个线程出现,但在双核机器上创建4个线程并不能真正提高性能,因为只有2个线程可以同时处于活动状态。
此外,对于基于IO的操作,任何额外的线程都可能只是阻塞执行的第一个IO操作。
答案 1 :(得分:4)
答案 2 :(得分:2)
看来PLINQ会调整线程数。当我在一个while(true)循环中包装上面的代码时,前两次迭代需要两秒钟才能运行,但第三次和以上只需要一秒钟。 PLINQ了解核心是空闲的并且增加了线程数量。可观!
答案 3 :(得分:-1)
我同意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个线程。