电脑CPU是电脑的核心,CPU是中央处理器,是电脑进行线程调度的关键,可以通过查看电脑CPU性能个数可以判定电脑的性能。
CPU个数即CPU芯片个数。 (下图是单CPU双核心 逻辑核心4个{超线程技术})
CPU内核是CPU中间的核心芯片,由单晶硅制成,用来完成所有的计算、接受/存储命令、处理数据等,是数字处理核心。核心(Die)又称为内核,是CPU最重要的组成部分。CPU中心那块隆起的芯片就是核心,是由单晶硅以一定的生产工艺制造出来的,CPU所有的计算、接受/存储命令、处理数据都由核心执行。各种CPU核心都具有固定的逻辑结构,一级缓存、二级缓存、执行单元、指令级单元和总线接口等逻辑单元都会有科学的布局。
超线程技术:一个核心可以对应两个线程,也就是说它可以同时运行两个线程。
多进程:适用于密集CPU任务, 可以充分调度CPU资源(大量的并行运算)。 multiprocessing 缺点:不适用于需要大量数据通信和多次切换的场景,因为进程之间通信和切换成本高。
多线程:适用于密集IO任务(网络IO,磁盘IO,数据库IO), 在IO阻塞时可以切换线程执行。 threading.Thread、multiprocessing.dummy 缺点:同一个CPU时间片只能执行一个任务,不能做到并行,只能做到并发。优点:线程之间切换和通信非常方便,开销小。
由程序员自行编写调度功能, 切换协程就好比切换一个函数, 几乎没有切换开销。
特点是在单线程上执行多个任务, 调度由程序员控制,不经过操作系统, 所以没有进程线程的切换开销, 也不需要处理锁。
gevent monkey.patch_all() monkey的作用是将Python底层的网络库socket、select自动打个补丁, 程序在遇到网络IO阻塞时, 可以自动切换协程工作。
(该补丁不适用于本地IO)
优点:协程任务是基于用户的,不经过操作系统,执行效率极高。 缺点:单线程执行,不能处理 CPU密集任务,和密集本地IO任务。
进程: 表示一个程序的执行活动 (打开程序、读写程序数据、关闭程序)
线程: 执行某个程序时, 该进程调度的最小执行单位 (执行功能1,执行功能2) 一个程序至少有一个进程 一个进程至少有一个线程
并行: 需要处理的任务数 == CPU核心数量 两个任务 两个核心 任务1:------------- 任务2:-------------
并发: 需要处理的任务数 > CPU核心数量 三个任务 一个核心 任务1: ----- ------ 任务2: ------ 任务3: ------
首先需要明确的一点是GIL
并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念。就好比C++是一套语言(语法)标准,但是可以用不同的编译器来编译成可执行代码。有名的编译器例如GCC,INTEL C++,Visual C++等。Python也一样,同样一段代码可以通过CPython,PyPy,Psyco等不同的Python执行环境来执行。像其中的JPython就没有GIL。然而因为CPython是大部分环境下默认的Python执行环境。所以在很多人的概念里CPython就是Python,也就想当然的把GIL
归结为Python语言的缺陷。所以这里要先明确一点:GIL并不是Python的特性,Python完全可以不依赖于GIL
那么CPython实现中的GIL又是什么呢?GIL全称Global Interpreter Lock.
“python下想要充分利用多核CPU,就用多进程”,原因是什么呢?
原因是:每个进程有各自独立的GIL,互不干扰,这样就可以真正意义上的并行执行,(多线程并不是真正意义上的并行执行,只能算并发执行)所以在python中,多进程的执行效率优于多线程(仅仅针对多核CPU而言)。
由于现实生活中运行的总进程数量总是多于 CPU核心数量!因此,严格来说并没有真正意义上的并行。现在运行的程序都是轮询调度产生的并行假象,所以如何根据实际情况选择多进程或是多线程。