CPU 与并发
目录
¶CPU 相关术语
🤔程序都运行在 CPU 之上,那么 CPU 的核心数和线程数之间是什么关系尼?答案隐藏在本文中
¶物理 CPU 数(Physical CPU)
✨Physical CPU 指的是:主板上实际插入的 CPU 硬件个数
😣但是这一概念经常被泛泛的说成是 cpu 数,这很容易导致与 core 数,processor 数等概念混淆
🎶由于在主板上引入多个 CPU 插槽(socket)需要更复杂的硬件支持(连接不同插槽的 CPU 到内存和其他资源),通常只会在服务器才会插多个物理 CPU,家用 PC 机的主板上只会有一个 CPU 插槽
¶核心(Core)
最初,每个物理 CPU 上只有一个核心(single core),此时对于操作系统而言,同一时刻只能运行一个进程/线程;随着摩尔定律的生效,CPU 厂商开始在单个物理 cpu 上增加核心(实实在在的硬件存在),此时单核心物理 CPU变成了双核心 cpu(dual-core cpu)以及多核心 cpu(multiple cores),如此一来,操作系统就能在同一时刻运行多个进程/线程
一个双核心 cpu 就是操作系统同一时刻能够运行两个进程/线程的物理设备,下图是多核心 CPU 的示意图
¶同时多线程技术(simultaneous multithreading)和超线程技术(hyper–threading/HT)
🎯同时多线程技术和超线程技术的本意是:提高单个 CPU 核心同一时刻能够执行的多线程数,充分利用单个 CPU Core 的计算能力
simultaneous multithreading 缩写 SMT,是 AMD 和其他 CPU 厂商的称呼
hyper–threading 是 Intel 的称呼,可以认为 hyper–threading 是 SMT 的一种具体技术实现
✨在类似的多线程技术下,产生了如下等价的术语:
- 虚拟核心:virtual core
- 逻辑处理器:logical processor
- 线程:thread
¶查看系统 CPU 资源
¶Linux 系统
1 | #查看物理 cpu 数 |
¶Windows 系统
¶CPU 的并发
CPU 本身并没有线程和进程的概念,它只会按照机器指令的要求执行某个动作,线程以及进程等概念是从操作系统角度看待任务产生的两个概念,因此宏观角度看待CPU 不存在并发性抽象,并发的抽象发生在操作系统层级
🎶CPU 的核心数和线程个数有什么必然的关系吗?(没有任何关系)
- 单个核心可以跑任意多个线程,只要计算机内存足够就可以;
- 计算机可以有多核但只运行单线程
📓CPU 与并发的总结
- CPU 根本不理解自己执行的指令属于哪个线程,CPU 也不需要理解这些,CPU 需要做的事情就是根据 PC 寄存器中的地址从内存中取出响应的指令,然后执行就足够了
- 计算机中应该存在多少线程,线程之间如何运行都是操作系统应该操心的事情,CPU 根本不用考虑这些问题,它只需要执行任务就可以了
¶操作系统的并发
✨操作系统的并发来自于操作系统的多任务特点
🤔什么是操作系统的多任务?
- 多任务就是在操作系统的管理下(通过修改 CPU 的 PC 寄存器),能够在一段时间内执行多个任务(多个线程)
- 多任务是并行/并发的雏形
¶进程与线程
🆚CPU 与 OS 如何看待进程和线程
- CPU 不知道执行的某一段机器指令属于 A 任务还是 B 任务,其内部没有进程和线程的抽象
- 操作系统知道机器指令属于哪个任务,同时操作系统还能知道任务 A 和 B 任务是否属于同一个地址空间
如果两个任务属于同一个地址空间,那么任务 A 和任务 B 就是我们熟悉的多线程;如果不属于同一个地址空间,那么任务 A 和任务 B 就是我们熟悉的多进程
¶单核与多线程
假设现在有两个任务,任务 A 和任务 B,每个任务需要的计算时间都是 5 分钟,那么无论是任务 A 和任务 B 串行执行还是放到两个线程中并行执行,在单核环境下执行完这两个任务总需要 10 分钟
🎶由于核心数是固定的,再怎么并发,单核心上再某一时刻,只能执行一个任务
👴线程概念为程序设计人员提供了一种变成抽象,可以将一项任务进行划分,然后把每一个子任务放到一个个线程中运行
📖单核多线程的案例(阻塞式 I/O)
- 如果没有多线程,执行阻塞式 I/O 时整个进程会被操作系统暂停,但如果开启两个线程,其中一个线程被阻塞时另一个线程依然可以继续向前推进,就可以充分利用系统资源
¶总结
🎶CPU 自身对于并发还是并行是不敏感的,这些都是我们在操作系统层面讨论的东西,CPU 唯一限制开发人员的就是:CPU 所具有的物理性质(核心数目),就是再优秀的并发算法,在单核 CPU 上,表现的性能比串行性能差
🤔为了让多线程程序更好的利用 cpu 资源,应当如何做到 CPU 与线程数的权衡尼?
- 对于计算密集型程序的建议是:
(logical processor count ) + 1
,有的建议是(logical processor count)*1.5
,但是大部分都是经验之谈,需要根据实际业务场景进行测试才能得到适合自己的答案
❓那么如何了解机器拥有的 logical processor 数尼?
cpuinfo
中查看:cat /proc/cpuinfo | grep "processor" | wc -l
top
命令查看:cpu0,cpu1,...
- 编程:比如在 Java 中用
Runtime.getRuntime().availableProcessors()