python高性能编程第一章读书笔记

计算机底层组件分为三大基本部分:计算单元、存储单元以及两者之间的连接。

计算单元:具有将接收到的任意输入转换成输出的能力以及改变当前处理状态的能力。CPU是最常见的计算单元。它的主要属性是其每个周期能进行的操作数量以及每秒能完成多少个周期。第一个属性通过每周期完成的指令数(IPC)来衡量。第二个属性通过其时钟速度来衡量。时钟速度的提高,可以使得每秒进行更多的计算,提高该计算单元所有程序的运行速度。IPC的提高则在矢量计算能力上有相当程度的影响。矢量计算指的是一次提供多个数据给一个CPU并能同时被操作。这种类型的CPU指令被称为SIMD(单指令多数据)。

         由于时钟速度和IPC提升陷入停滞,开始依靠超线程技术,乱序执行和多核架构来提高速度。超线程技术为主机的操作系统(OS)虚拟了第二个CPU,硬件逻辑则试图将两个指令线程交错地插入单个CPU的执行单元。乱序执行允许编译器检测出一个线性程序中某部分可以不依赖于之前的工作,也就是说两个工作能够以各种顺序执行或同时执行。使得当一些指令被阻塞(比如等待一次内存访问),另一些指令得以执行。多核架构指的是给CPU增加更多的核心。但是不一定多核就会更快,阿姆达尔定律认为:如果一个可以运行在多核上的程序有某些执行路径必须运行在单核上,那么这些路径就会成为瓶颈导致最终速度无法加快。

         对于python来说,python的全局解释器锁(GIL),确保Python进程一次只能执行一条指令,无论当前有多少个核心。使得无法使用多核,但是我们可以使用标准库的multiprocessing,或numexpr、Cython技术,或分布式计算模型来避免。

         存储单元,用于保存比特。比如主板上的寄存器、RAM以及硬盘。所有这些不同类型的存储单元主要区别在于读写数据的速度。且速度与读写方式有关,如顺序读取要比随机读取快得多。此外还有延时来表示设备查找数据所花费的时间。

         比如说判断一个数是否为质数,首先将number的值保存在RAM中。为了计算sqrt_number和number_float,将该值传入CPU中,理想情况下只需要传一次,它将被保存在CPU的L1/L2缓存中,然后CPU进行两次计算并将结果传回RAM保存。在循环部分,我们更希望一次就将number——float和多个i的值传入CPU进行检查。

         Python虚拟机抽象层的影响之一就是矢量操作变得不是直接可用。而numpy这样的外部库可以通过增加矢量化数学操作来帮助我们解决这个问题。

         Python抽象还影响了任何需要为下一次计算保存L1/L2缓存中相关数据的优化。首先是python对象不再是内存中最优化的布局。这是因为python是一种垃圾收集语言----内存会被自动分配并在需要时释放。这会导致内存碎片并影响CPU缓存的传输。

         Python的优势在于可以轻易调用其他系统,正确运用库可以使python代码在速度上和c媲美。

猜你喜欢

转载自blog.csdn.net/ma412410029/article/details/80489405