高性能扩展#
1. 默认环境#
1.1. 三组概念#
代码
源代码:即使用某种编程语言编写的代码
目标代码:即二进制的机器码
源代码处理
编译:将源代码一次性变换为目标代码的过程
解释:将源代码逐条变换为目标代码,并运行的过程
执行方式
静态语言:使用编译器执行的编程语言,如 C/C++,Java
动态语言:使用解释器执行的编程语言,也叫脚本语言,如 Python,JavaScript
2. 标准工作站#
计算单元
中央处理单元(central processing unit,CPU)
存储单元
L1/L2 缓存
图形处理单元(graphical processing unit,GPU)
存储单元
随机访问内存(random access memory,RAM)
硬盘
总线(bus)
前端总线:连接 L1/L2 缓存和 RAM
后端总线:
2.1. 计算单元#
Amdahl’s 定律认为提升系统的一部分性能时,对整个系统性能的影响取决于:
这一部分有多重要
这一部分性能提升了多少
假设原来在一个系统中执行一个程序需要时间\(T_\mathrm{old}\),其中,某一个部分占的时间百分比为\(α\),然后,把这一部分的性能提升\(k\)倍。即这一部分原来需要的时间为\(αT_\mathrm{old}\),现在需要的时间变为\(αT_\mathrm{old}/k\)。则整个系统执行此程序需要的时间变为:
故可得,系统性能提速的倍数为:
简单地说,Amdahl’s 定律认为若一个可以运行在多核上的程序有某些执行路径必须运行在单核上,则这些路径就会成为瓶颈导致最终速度无法通过增加更多核心来提高。
对于 Python 来说,充分利用多核性能的阻碍主要在于 Python 的全局解释器锁(GIL)。GIL 确保 Python 进程一次只能执行一条指令,无论当前有多少个核心。
这意味着即使某些 Python 代码可以使用多个核心,在任意时间点仅有一个核心在执行 Python 的指令。
2.2. 存储单元#
旋转硬盘 计算机关机也能保持的长期存储。读写速度通常较慢,因为磁盘必须物理旋转和等待磁头移动。随机访问性能下降但容量很高(TB 级别)。
固态硬盘 类似旋转硬盘,读写速度较快但容量较小(GB 级别)。
RAM 用于保存应用程序的代码和数据(比如用到的各种变量)。具有更快的读写速度且在随机访问时性能良好,但通常受限于容量(GB 级别)。
L1/L2 缓存 极快的读写速度。进入 CPU 的数据必须经过这里。很小的容量(KB 级别)。
一个清晰可见的趋势是读写速度和容量成反比。因此,很多系统都实现了一个分层的存储:
数据在硬盘里
部分进入 RAM
很小的一个子集进入 L1/L2 缓存
这种分层使得程序可以根据访问速度的需求将数据保存在不同的地方。在试图优化程序的存储访问模式时,只是简单优化了数据存放的位置、布局(为了增加顺序读取的次数),以及数据在不同位置之间移动的次数。
另外,异步 I/O 和缓存预取等技术还提供了很多方法来确保数据在被需要时就已经存在于对应的地方。
2.3. 通信层#
通信有很多模式,但它们都是同一样东西的变种:总线。
总线(Bus)是计算机各种功能部件之间传送信息的公共通信干线,它是由导线组成的传输线束。
总线按功能和规范可分为五大类型:
系统总线(狭义总线)
数据总线(Data Bus):在 CPU 与 RAM 之间来回传送需要处理或是需要储存的数据。
地址总线(Address Bus):用来指定在 RAM 中储存的数据的地址。
控制总线(Control Bus):将微处理器控制单元(Control Unit)的信号,传送到周边设备。
扩展总线(Expansion Bus):外部设备和计算机主机进行数据通信的总线。
ISA 总线
PCI 总线
局部总线(Local Bus):取代更高速数据传输的扩展总线。
3. C 扩展#
加速器
标准库
datatime
的_datatimemodule.c
实现
装饰器
标准库
functools
的_functoolsmodule.c
实现
底层入口
标准库
sys
的_sysmodule.c
实现