Python高性能编程
Python 高性能编程简述
1. 计算机基本系统
思考:
实现高性能 Python 代码的障碍在哪里?
性能问题有哪些种类?
一台计算机底层组件可分为: 计算单元、存储单元、两者间连接
1.1 计算单元
计算单元,即将接收到任意输入(比特 )转为输出(计算后的比特 )的能力,以及改变当前处理状态的能力,即 CPU 是最常见的计算单元,当然 之前设计与图形加速的处理单元 GPU 如今也更适合用于数值计算了
主要属性:
- IPC: 每(指令 )周期完成指令数,影响 矢量计算 (一次提供多数据给 一个 CPU 同时操作 )
- 时钟速度: 目前理解为程序的切换速度,速度提高,会立即 提高计算单元所有程序的运行速度
这两个参数是互斥的,但 GPU 中,两参数可以都很高(但有别的问题 )
超线程技术:
由于晶体管已经缩小至极限, IPC 和 时钟 已到达极限,芯片厂商研制了超线程技术,即 更聪明的乱序执行 和 多核操作,它为 OS 虚拟了第二个 CPU ,将 两个 指令线程 交错插入 CPU 的 不同执行单元(如:一个操纵整数、一个操纵浮点数),若插入成功,则计算性能比单线程提升 30%
- 乱序: 允许 编译器 检测出线性程序 无依赖 的部分,各种顺序执行都不会影响正确结果,即 计算次序与程序设计不同,也能正确运行,这就使得一些 指令阻塞 时(如:等待一次内存访问 )另一些指令也得以执行,以此来提升资源的利用率。
- 多核架构: 在同一个计算单元中包含了 多个 CPU ,提高了总体计算能力,且无需等待内存屏障,让单个核心跑的更快
阿姆达尔定律
多核不一定意味着速度的提升 ,一个可以运行在多核上的程序,有某些 路径 必须运行在单核上,那么这些 路径 就是瓶颈导致最终速度无法通过 增加更多核心来提高
因此,任何并行计算的瓶颈最终都会落在顺序执行的那部分任务上
对于 Python 来说,充分利用多核性能的阻碍主要在于 GIL(Python 的全局解释器锁 ) ,它确保无论有多少核心,Python 进程一次也只能执行一条指令,即使代码可使用多核心,但在任意一个时间点上,也仅有一个核心在执行 Python 的指令,好在这个问题可以通过标准库的 multiprocessing 或 numexpr 、 Cpython 等技术,或分布式计算模型来解决
1.2 存储单元
存储单元,用于 保存比特,这些比特可能是程序中的变量、一副图片的像素等。其包括了主板上的 寄存器 、 RAM 以及 硬盘 ,不同类型、介质、协议的存储单元的区别在于其 读写数据的速度,更复杂的问题在于其速度还与 读写数据的方式(顺序、随机 ) 的方式有关
如大多数存储单元 一次读一大块数据的性能远好于读多次小块数据,将其想象成一本书中的书页,大多数存储单元的读写速度在连续翻页时高于从一张随机页跳至另一张随即页
1.3 通信层
上述基本单元通信,需要依赖 总线