为何MaxDegreeOfParallelism升高时Parallel.For单核心CPU使用率下降
并行度提升后单核心CPU占用下降的原因分析
你测试所用的代码如下:
public static void myTest() { Parallel.For(0, 50,new ParallelOptions { MaxDegreeOfParallelism = 20 }, (kk) => { List<int> mylist = new List<int>(); while (true) { mylist.Add(1); if (mylist.Count > 500000) { mylist = new List<int>(); } } }); }
测试截图:
核心原因如下:
- 这个负载不是纯CPU计算型负载,而是内存分配+垃圾回收密集型负载。你误以为局部变量无共享就不存在资源竞争,但实际上.NET的托管堆、垃圾回收是所有线程共享的全局资源,会产生大量同步开销。
- 代码中生成的
List<int>长度超过50万时,单个数组占用空间达到2MB,远大于.NET默认85000字节的大对象阈值,会被分配到大对象堆(LOH)。LOH的分配需要获取全局锁,并行度越高,多个线程抢锁的等待时间越长,线程等待时不会占用CPU,直接拉低单核心使用率。 - 并行度设为1时,没有锁竞争、也没有线程上下文切换开销,线程可以全程占用核心跑业务逻辑,所以CPU占用直接拉满100%。
- 当并行度达到20时,如果数值超过你设备的CPU物理核心数,操作系统需要频繁在20个线程之间做上下文切换,切换过程的开销不属于业务计算范畴,也会降低单核心的有效计算占比。
- 频繁的大对象分配会触发高频垃圾回收,GC的Stop The World(STW)阶段会挂起所有工作线程,这段时间核心不会执行业务代码,进一步降低了CPU的有效使用率。
内容的提问来源于stack exchange,提问作者SandiaDeDia
相关产品推荐
相关产品推荐

