重新理解python解释器

Python解释器做了大量的工作,力图对程序员隐藏它使用的计算部件。

这让程序员根本不用考虑如下问题:如何给数组分配内存、如何组织这些内存以及其中的数据是以什么样的顺序发送给CPU的。

这是Python的一个优势,让程序员能够专注于要实现的算法,但付出的代价是性能可能急剧下降。

需要指出的是,Python运行的确实是经过极度优化的指令,但你需要掌握一些诀窍,让Python以正确的顺序执行这些指令,以进一步提高性能。

例如,在下面的示例中,search_fast的速度比search_slow快,这很容易判断出来,这是因为虽然这两个函数的运行时间都是O(n),但search_fast通过提前结束循环避免了多余的计算。

然而,在涉及派生类型、特殊的Python方法或第三方模块时,情况可能更复杂。

例如,对于下面的函数search_unknown1和search_unknown2,你能迅速判断出哪个的速度更快吗?

def search_fast(haystack, needle):

    for item in haystack:

        if item == needle:

            return True

    return False

 

def search_slow(haystack, needle):

    return_value = False

    for item in haystack:

        if item == needle:

            return_value = True

    return return_value

 

def search_unknown1(haystack, needle):

    return any((item == needle for item in haystack))

 

def search_unknown2(haystack, needle):

    return any([item == needle for item in haystack]

前面演示的是找出无用操作并将其删除,与之类似的是通过剖析找出速度缓慢的代码,并寻找效率更高的计算方式。

虽然最终的结果是一样的,但通过这样做,可极大地减少计算次数和数据传输次数。

前述抽象层带来的影响之一是,无法直接利用向量化。

在前述判断素数的函数中,对于每个i值都将运行一次循环迭代,而不会将多个迭代合并。

如果你再看看前述向量化示例,将发现它并非合法的Python代码,因为在Python中,不能将浮点数与列表相除。

在这种情况下,诸如numpy等外部库可提供帮助,它让你能够执行向量化数学运算。

另外,Python所做的抽象还会影响这样的优化,即它依赖于将相关的数据保留在L1/L2缓存中,以供下一次计算时使用。导致这种结果的原因很多。

首先,Python对象在内存中并不是以最优方式排列的。这是因为Python是一种垃圾收集语言——根据需要自动分配和释放内存。

这会导致内存碎片,进而可能影响将数据传输到CPU缓存的过程。

与此同时,你无法直接调整数据结构在内存中的排列,这意味着即便与特定计算相关的数据量低于总线宽度,也可能无法通过总线一次性传输它们[插图]。

其次,Python不是编译型语言,且其使用的类型是动态的。

凭借多年的经验,很多C语言程序员都发现,编译器通常比自己聪明。编译静态代码时,编译器能够巧妙地调整布局以及CPU运行指令的方式,从而对代码进行优化。

Python不是编译型语言,雪上加霜的是,其类型是动态的,这意味着根据算法推断出可能的优化机会要难得多,因为在运行期间,代码的功能可能发生变化。

缓解这种问题的途径有很多,其中居首的是使用Cython,它让Python代码能够被编译,还让开发人员能够将代码的动态程度告知编译器。

最后,前面提到的GIL也可能影响并行代码的性能。例如,假设为利用多个CPU核心对前述代码进行修改,让每个核心处理2~sqrtN的一个子范围。

每个核心都可独立地处理分配给它的子范围,再在处理完毕后比较结果。

虽然这样做会失去提前结束循环的好处(因为每个核心都不知道其他核心的处理结果),但可减少缩小每个核心需要处理的数字范围(如果有M个核心,则每个核心需要做的检查将为sqrtN/M次)。

但是,由于GIL的存在,不能同时使用多个核心。

这意味着效果与非并行版本相同,而且不能提前结束循环。

为避免这种问题,可使用模块multiprocessing实现多进程(而不是多线程),还可使用Cython或外部函数。

 

  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值