线程池的核心线程数 设置大小与cpu 的关系

1.线程池和CPU核心数的关系

一般说来,大家认为线程池的大小经验值应该这样设置:(其中N为CPU processors的个数)
(1)如果是CPU密集型应用,则线程池大小设置为N+1(或者是N),线程的应用场景:主要是复杂算法
(2)如果是IO密集型应用,则线程池大小设置为2N+1(或者是2N),线程的应用场景:主要是:数据库数据的交互,文件上传下载,网络数据传输等等
+1的原因是:即使当计算密集型的线程偶尔由于缺失故障或者其他原因而暂停时,这个额外的线程也能确保CPU的时钟周期不会被浪费。

补一下概念 :

1. CPU密集型(CPU-bound)

CPU密集型也叫计算密集型,指的是系统的硬盘、内存性能相对CPU要好很多,此时,系统运作大部分的状况是CPU Loading 100%,CPU要读/写I/O(硬盘/内存),I/O在很短的时间就可以完成,而CPU还有许多运算要处理,CPU Loading很高。

在多重程序系统中,大部份时间用来做计算、逻辑判断等CPU动作的程序称之CPU bound。例如一个计算圆周率至小数点一千位以下的程序,在执行的过程当中绝大部份时间用在三角函数和开根号的计算,便是属于CPU bound的程序。

CPU bound的程序一般而言CPU占用率相当高。这可能是因为任务本身不太需要访问I/O设备,也可能是因为程序是多线程实现因此屏蔽掉了等待I/O的时间。

2. IO密集型(I/O bound)

IO密集型指的是系统的CPU性能相对硬盘、内存要好很多,此时,系统运作,大部分的状况是CPU在等I/O (硬盘/内存) 的读/写操作,此时CPU Loading并不高。

I/O bound的程序一般在达到性能极限时,CPU占用率仍然较低。这可能是因为任务本身需要大量I/O操作,而pipeline做得不是很好,没有充分利用处理器能力。

一般说来,大家认为线程池的大小经验值应该这样设置:(其中N为CPU processors的个数)
(1)如果是CPU密集型应用,则线程池大小设置为N+1(或者是N),线程的应用场景:主要是复杂算法
(2)如果是IO密集型应用,则线程池大小设置为2N+1(或者是2N),线程的应用场景:主要是:数据库数据的交互,文件上传下载,网络数据传输等等
+1的原因是:即使当计算密集型的线程偶尔由于缺失故障或者其他原因而暂停时,这个额外的线程也能确保CPU的时钟周期不会被浪费。
如果一台服务器上只部署这一个应用并且只有这一个线程池,那么这种估算或许合理,具体还需自行测试验证。
但是,IO优化中,这样的估算公式可能更适合:
最佳线程数目 = ((线程等待时间+线程CPU时间)/线程CPU时间 )* CPU数目。
因为很显然:
(1)线程等待时间所占比例越高,需要越多线程。
(2)线程CPU时间所占比例越高,需要越少线程。
eg:
比如平均每个线程CPU运行时间为0.5s,而线程等待时间(非CPU运行时间,比如IO)为1.5s,CPU核心数为8,
那么根据上面这个公式估算得到:
((0.5+1.5)/0.5)8=32。
这个公式进一步转化为:最佳线程数目 = (线程等待时间与线程CPU时间之比 + 1)
CPU数目。
刚刚说到的线程池大小的经验值,其实是这种公式的一种估算值。

比如平均每个线程CPU运行时间为0.5s,而线程等待时间(非CPU运行时间,比如IO)为1.5s,CPU核心数为8,
那么根据上面这个公式估算得到:
((0.5+1.5)/0.5)*8=32。
这个公式进一步转化为:最佳线程数目 = (线程等待时间与线程CPU时间之比 + 1* CPU数目。
刚刚说到的线程池大小的经验值,其实是这种公式的一种估算值。

2.常见概念:CPU的核心数,CPU的线程数
CPU的核心数:
CPU的核心数是指物理上,也就是硬件上存在着几个核心。
比如,双核就是包括2个相对独立的CPU核心单元组,四核就包含4个相对独立的CPU核心单元组
CPU的线程数:
对于一个CPU,线程数总是大于或等于核心数的。
(1)一个核心最少对应一个线程,但通过超线程技术,一个核心可以对应两个线程,也就是说它可以同时运行两个线程。
(2)CPU之所以要增加线程数,是源于多任务处理的需要。线程数越多,越有利于同时运行多个程序,因为线程数等同于在某个瞬间CPU能同时并行处理的任务数。
eg:
在Windows中,在cmd命令中输入“wmic”,然后在出现的新窗口中输入“cpu get *”即可查看物理CPU数、CPU核心数、线程数。
其中:
Name:表示物理CPU数
NumberOfCores:表示CPU核心数
NumberOfLogicalProcessors:表示CPU线程数

(1)CPU的线程数概念仅仅只针对Intel的CPU才有用,因为它是通过Intel超线程技术来实现的
(2)如果没有超线程技术,一个CPU核心对应一个线程。 所以,对于AMD的CPU来说,只有核心数的概念,没有线程数的概念。

在Windows中,在cmd命令中输入“wmic”,然后在出现的新窗口中输入“cpu get *”即可查看物理CPU数、CPU核心数、线程数。
其中:
Name:表示物理CPU数
NumberOfCores:表示CPU核心数
NumberOfLogicalProcessors:表示CPU线程数


(1)CPU的线程数概念仅仅只针对Intel的CPU才有用,因为它是通过Intel超线程技术来实现的
(2)如果没有超线程技术,一个CPU核心对应一个线程。 所以,对于AMD的CPU来说,只有核心数的概念,没有线程数的概念。

3.是否使用线程池就一定比使用单线程高效呢?
答案是否定的,比如Redis就是单线程的,但它却非常高效,基本操作都能达到十万量级/s。从线程这个角度来看,部分原因在于:
(1)多线程带来线程上下文切换开销,单线程就没有这种开销
(2)锁

当然“Redis很快”更本质的原因在于:
Redis基本都是内存操作,这种情况下单线程可以很高效地利用CPU。而多线程适用场景一般是:存在相当比例的IO和网络操作。

所以即使有上面的简单估算方法,也许看似合理,但实际上也未必合理,都需要结合系统真实情况(比如是IO密集型或者是CPU密集型或者是纯内存操作)和硬件环境(CPU、内存、硬盘读写速度、网络状况等)来不断尝试达到一个符合实际的合理估算值。

https://blog.csdn.net/u011436427/article/details/103744149?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromBaidu-1.control&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromBaidu-1.control

猜你喜欢

转载自blog.csdn.net/weixin_43975771/article/details/113099180