天天看点

IO密集型和CPU密集型如何区分

CPU 密集型

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

IO密集型和CPU密集型如何区分

比如说要计算1+2+3+…+ 1亿、计算圆周率后几十位、数据分析。都是属于CPU密集型程序。

此类程序运行的过程中,CPU占用率一般都很高。

假如在单核CPU情况下,线程池有6个线程,但是由于是单核CPU,所以同一时间只能运行一个线程,考虑到线程之间还有上下文切换的时间消耗,还不如单个线程执行高效。

所以!!!单核CPU处理CPU密集型程序,就不要使用多线程了。

假如是6个核心的CPU,理论上运行速度可以提升6倍。每个线程都有 CPU 来运行,并不会发生等待 CPU 时间片的情况,也没有线程切换的开销。

所以!!!多核CPU处理CPU密集型程序才合适,而且中间可能没有线程的上下文切换(一个核心处理一个线程)。

简单的说,就是需要CPU疯狂的计算。

IO密集型

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

IO密集型和CPU密集型如何区分

所以用脚本语言像python去做I/O密集型操作,效率就很快。

简单的说,就是需要大量的输入输出,例如读文件、写文件、传输文件、网络请求。

区别和使用:

计算密集型任务的特点是要进行大量的计算,消耗CPU资源,比如计算圆周率、对视频进行高清解码等等,全靠CPU的运算能力。这种计算密集型任务虽然也可以用多任务完成,但是任务越多,花在任务切换的时间就越多,CPU执行任务的效率就越低,所以,要最高效地利用CPU,计算密集型任务同时进行的数量应当等于CPU的核心数。

一般来说:计算型代码、Bitmap转换、Gson转换等

计算密集型任务的特点是要进行大量的计算,消耗CPU资源,比如计算圆周率、对视频进行高清解码等等,全靠CPU的运算能力。

这种计算密集型任务虽然也可以用多任务完成,但是,任务越多,花在任务切换的时间就越多,CPU执行任务的效率就越低,

所以,要最高效地利用CPU,计算密集型任务同时进行的数量应当等于CPU的核心数。

计算密集型任务由于主要消耗CPU资源,因此,代码运行效率至关重要。Python这样的脚本语言运行效率很低,完全不适合计算密集型任务。对于计算密集型任务,最好用C语言编写。

第二种任务的类型是IO密集型,涉及到网络、磁盘IO的任务都是IO密集型任务,这类任务的特点是CPU消耗很少,任务的大部分时间都在等待IO操作完成(因为IO的速度远远低于CPU和内存的速度)。对于IO密集型任务,任务越多,CPU效率越高,但也有一个限度。常见的大部分任务都是IO密集型任务,比如Web应用。

一般来说:文件读写、DB读写、网络请求等

第二种任务的类型是IO密集型,涉及到网络、磁盘IO的任务都是IO密集型任务,这类任务的特点是CPU消耗很少,

任务的大部分时间都在等待IO操作完成(因为IO的速度远远低于CPU和内存的速度)。

对于IO密集型任务,任务越多,CPU效率越高,但也有一个限度。常见的大部分任务都是IO密集型任务,比如Web应用。

IO密集型任务执行期间,99%的时间都花在IO上,花在CPU上的时间很少,因此,用运行速度极快的C语言替换用Python这样运行速度极低的脚本语言,完全无法提升运行效率。对于IO密集型任务,最合适的语言就是开发效率最高(代码量最少)的语言,脚本语言是首选,C语言最差。

如何确定线程池大小?

线程数不是越多越好。

由于CPU的核心数有限,线程之间切换也需要开销,频繁的切换上下文会使性能降低,适得其反。

IO密集型和CPU密集型如何区分

简单的总结就是:

Ncpu 表示 核心数。如果是CPU密集型任务,就需要尽量压榨CPU,参考值可以设为 Ncpu+1

如果是IO密集型任务,参考值可以设置为 2 * Ncpu

上面两个公式为什么是Ncpu+1 呢,而不是Ncpu+2 呢,为什么不是3 * Ncpu 呢?

这样来计算线程池的线程数目的:

一个基准负载下,使用 几种不同大小的线程池运行你的应用程序,并观察CPU利用率的水平。给定下列定义:

IO密集型和CPU密集型如何区分

为保持处理器达到期望的使用率,最优的池的大小等于:

Nthreads = Ncpu x Ucpu x (1 + W/C)      

CPU数量是确定的,CPU使用率是目标值也是确定的,W/C也是可以通过基准程序测试得出的。

对于计算密集型应用,假定等待时间趋近于0,是的CPU利用率达到100%,那么线程数就是CPU核心数,那这个+1意义何在呢?

计算密集型的线程恰好在某时因为发生一个页错误或者因其他原因而暂停,刚好有一个“额外”的线程,可以确保在这种情况下CPU周期不会中断工作。      

所以 Ncpu+1 是一个经验值。

对于IO密集型应用,假定所有的操作时间几乎都是IO操作耗时,那么 W/C的值就为1,Ucpu 要达到100%利用率。

根据 Nthreads = Ncpu x Ucpu x (1 + W/C),

那么对应的线程数确实为 2Ncpu 。

Java代码中可以通过Rumtime来获得CUP的数目:

int N_CPUS = Runtime.getRuntime().availableProcessor();      

对于包含I/O操作或者其他阻塞的任务,由于线程不会一直执行,因此线程池的数量应该更多。

有一个思路,CPU计算和IO的阻抗匹配原则。

如果线程池中的线程在执行任务时,密集计算所占的时间比重为P(0<P<=1),而系统一共有C个CPU,为了让CPU跑满而又不过载,线程池的大小经验公式 T = C / P。在此,T只是一个参考,考虑到P的估计并不是很准确,T的最佳估值可以上下浮动50%。

这个经验公式的原理很简单,T个线程,每个线程占用P的CPU时间,如果刚好占满C个CPU,那么必有 T * P = C。

如果一个web程序有CPU操作,也有IO操作,那该如何设置呢?

有一个估算公式:

最佳线程数目 = ((线程等待时间+线程CPU时间)/线程CPU时间 )* CPU数目      

这个公式进一步转化为:

最佳线程数目 = (线程等待时间与线程CPU时间之比 + 1)* CPU数目      

以上可以得出一个结论:

线程等待时间所占比例越高,需要越多线程。线程CPU时间所占比例越高,需要越少线程。

Prometheus监控(1)

三丰,公众号:soft张三丰Prometheus监控(1)

Prometheus监控(2)

三丰,公众号:soft张三丰Prometheus监控(2)

Prometheus监控(3)

三丰,公众号:soft张三丰Prometheus监控(3)

Prometheus监控(4)

三丰,公众号:soft张三丰Prometheus监控(4)

Prometheus监控(5)

三丰,公众号:soft张三丰Prometheus监控(5)

继续阅读