一、从计算机的发展说起:
① 真空管与穿孔卡片
输入一个指令,输出一个结果
② 晶体管和批处理系统
攒成一大波输入(批处理指令),然后顺序计算
③ 集成电路芯片和多道程序设计
开发出多道程序设计,将内存分为几个部分,每一部分存放不同的作业,如图所示。当一个作业等待IO完成时,另一个作业可以 使用CPU,内存中放足够的作业,则CPU的利用率能接近100%。(并发)
④ 个人计算机
大规模集成电路时代,实现了多线程,多核心,进入个人PC时代。
二、 线程和进程
1. 线程的由来
第三代计算机中,每一个进程处理一个程序,(单核+多道)实际上实现了多进程的并发处理,。
进程的定义:
进程就是一个程序在一个数据集上的一次动态执行过程。 进程一般由程序、数据集、进程控制块三部分组成。(程序,是一组指令的有序集合,可以理解成第二代计算机中的批处理指令)
这样做法虽然说进程之间是并行的,但是进程内部还是串行的,也就是说,如果进程内部一条指令发生阻塞(阻塞),那么同样会导致这个进程进行不下去,那么为了解决这个问题,就引入了线程这个概念,就是把进程进一步的细分为一个个线程,线程之间来回切换执行,这样我们系统调度的最小单位就变为了线程。
线程的出现:
① 是为了降低上下文切换的消耗,
② 提高系统的并发性,并突破一个进程只能干一样事的缺陷, 使到进程内并发成为可能。
2. 线程和进程的关系
① 一个程序至少有一个进程,一个进程至少有一个线程.(进程可以理解成线程的容器);
② 进程在执行过程中拥有独立的内存单元,而多个线程共享内存,各个线程共享资源;
③ 进程是资源分配和调度的最小单位,线程是是CPU调度和分派的基本单位,是进程的一个实体;
3. 多线程
- 进程之间,变量不共享,涉及到通信的问题,一般使用消息队列(此外还有管道,信号量等)
- 线程之间,多个线程修改同一个变量,涉及到同步的问题,使用锁来解决。
----- 示例程序:Python并发复习2 - 多线程模块threading的《生产者消费者模型》的多线程、多进程两种实现方式。
4. 多核心CPU的进程和线程
在单核时代实际上只能实现并发处理,即:
采取分时的方式,即把CPU的时间分成很多片段,某个时间片只能执行某个线程,虽然说从操作系统和CPU的角度来说还是串行处理的,但是由于CPU的处理速度很快,从用户的角度感觉是并行的。
随着计算机的发展,出现了多核cpu,实现了并行处理,如下图,多个线程之间不存在对CPU的抢占关系,而是微观上同时执行。
此处补充一下CPU核心数,线程数的概念:
- CPU的核心数是指物理上,也就是硬件上存在着几个核心。比如,双核就是包括2个相对独立的CPU核心单元组,四核就包含4个相对独立的CPU核心单元组。
- 线程数是一种逻辑的概念。通常来说,一个计算机核心在一瞬间只能执行一个线程,但是使用超线程技术(Intel才有,酷睿全系和志强部分处理器支持),一个核心可以同时运行两个线程,因此,线程数总是大于或等于核心数的。
三、 结论
综上分析,对于我们常见的CPU(多核心), 结论如下:
- Python和C/C++都是使用计算机的原生线程,因此在不考虑超线程技术的情况下,同时执行的最大线程数 == 计算机核心数。
- 对于计算密集型模拟软件(如Fluent, EDEM等),需要查看CPU和所用模拟软件(是否支持超线程,否则设置最大线程数等于总核心数,即可发挥最大性能。
参考博客: