Python 的低性能问题是无法忽视的
点击上方“CSDN”,选择“置顶公众号”
关键时刻,第一时间送达!
以前我常常说(虽然现在看法不同了):
从另外一个角度说,我发现现实世界中很多“性能”问题往往是由CPython解释器速度之外的因素引起的。没错,我希望解释器能快一些,但以我的经验看来,很多其他因素才是最主要的。至少,我们可以先从这些因素上想办法。
但是关于性能的讨论却很少提到其他非常重要且值得考虑的因素,比如说开发者的效率和编程经验。
这一点往往被低估,其实非常不应该!摩尔定律对人类并不适用,向项目中投入人手并不能有效地提高产出,也不能成比例地提高产出。Python是最好的开发语言和生态环境之一,其开发过程非常有趣,品质非常高,而且很有效率。
我以前一直认为,为提高效率而付出额外的努力部分原因是功利主义编程的表现。比如,额外花50个小时写一段代码,只为了让运行速度加快了1分钟,这是得不偿失的,除非这段代码会运行3000次以上。而在数据分析中很少有这种情况。现在我对这个问题的看法没有以前那么极端了。现在我认为CPython(唯一被广泛使用的Python解释器)很慢的事实是这个语言主要的劣势,并不是为了提高开发速度而付出的微小代价。
是什么让我改变了看法?
首先,我工作的内容变了。以前我的很多工作可以轻松地写成numpy的操作(numpy使用编译好的代码,所以速度很快),现在我写的很多代码与数值没有关系。其次,如果我必须使用标准的Python写代码的话,那么代码会慢得像乌龟爬。我的意思不是说“等几秒”的慢,而是说“两分钟的事情慢到需要等几个小时。”
同时,数据量越来越大,而计算机的核心(可惜Python没法简单地利用多核)也越来越多,但单个核心的性能提升却非常缓慢。所以,从性能方面来说,Python是越来越差的选择。
其他语言在运行高级代码时(使用JIT或激进的编译时优化),也能展现良好的性能。从旁观者的角度看来,Python的核心开发团队似乎对性能问题并不感兴趣。他们开展了许多优化的项目,如psyco、 unladen swallow、 stackless、 shedskin、pypy等,但只有最后一个项目处于积极的开发中。但是,尽管他们忙来忙去,这些成果却从来没能应用到CPython,以致于CPython还在沿用20年前的字节码堆栈机的策略。虽说优化一个非常动态的语言必须谨慎行事,但是Javascript也和Python一样是动态的,已经有几个基于JIT的实现了。
程序员的时间比计算机的时间更有价值,这话虽然没错,但是等待计算结果也是浪费我的时间。虽然我觉得我可以在等待期间做点别的事情,但是切换思路让我很头疼,所以我宁愿等待。
有时我还发现,为了让Python运行的程序快点,我经常会写一些十分复杂的代码,几乎没法读。比如这个函数(https://git.embl.de/costea/metaSNV/blob/master/metaSNV_post.py#L331)。第一次我们写了一个循环函数,直接引用计算公式。结果运行时间与中型(所谓中型指的是需要花费几周时间运行的问题)问题的运行时间差不多。现在,这个函数的运行减少到了几秒钟,但是除非你远比我聪明,否则要读懂代码中蕴含的公式可不是简单的事情。
结果我发现自己用Haskell做的东西越来越多,用Haskell可以写出性能良好(虽然性能还是不如C++,但是Haskell有很多很好的库)的高级代码。我还用Jug(基于Python)做连接,但是在运行中它会调用Haskell的代码完成功能。
现在有时我用Python创建原型,然后开始比赛:我在主数据集上运行分析,同时用Haskell重新实现整个功能。然后我运行Haskell版本,尽力在Python分析之前运行完毕。好多次,都是Haskell版本获胜(加上开发时间!)。
有天我遇到了一个很“有趣”的Python性能bug:删除10亿条字符串需要花费的时间超过12个小时。很显然这种情况可以解决,但是放在几年前,我肯定束手无策。以前10亿条字符串算是很多了,但现在我们感觉几TB的数据也“没什么大不了”。你可能没有遇到这样的事情,但是至少我是这样的。而且根据我在hackernews上的评论,我可以总结观点如下:
我主要的目的是为了节约总体花费时间,包括写代码的时间+运行代码的时间。
Python写代码的时间非常短,但是运行代码的时间却非常长。写代码的时间是人为因素(除了初学时的学习曲线外,我无法再有所提高)不计入内。但是一方面数据集越来越大,另一方面单个核心的性能又无法得到改善的情况下,运行代码的时间在不断增长,所以越来越值得花费更多时间优化代码,从而降低运行代码的时间。C++可以提供最短的运行代码时间,但是写代码的时间却太长(因为缺乏优秀的代码库和包管理)。所以至少对我来说Haskell是最好的选择。
上述方法适用于我的工作,因为我们使用大数据集作为输入,不过你的情况可能会有所不同。
此外针对以上的讨论,下面择取了hackernews上的部分观点,供大家参考。
观点一:文章讨论的是:Python的性能是否有问题?答案很显然:“有时会有问题,但你可以有别的选择。”
作者正是遇到了“有时”的情况,并且做出了自己的选择。你用Python做原型,并做连接,同时采用Haskell提高性能。这样的选择是很明智的。
我觉得没有Python的粉丝会说Python适合任何情况下的任何工作。我们通常会说,Python是每项工作的“首选”。用Python创建的系统,可以很快让你看到结果,从而判断仅采用Python是否足够。
观点二:我认为,性能永远很重要,而Python绝不是最好的工具。
就目前的环境来说,Python也许是正确的选择,但并不是说不存在可以与Python媲美同时还能提供良好性能的语言。比如像Nim或F#这些语言已经很接近了。而且,当我知道Python也有高性能的衍生版本时,我认为它们应该成为主要标准,而且是唯一的标准。速度缓慢的版本不应该再存在。
我们的社区让速度慢的语言蓬勃发展是个巨大的错误,因为慢速工具流行意味着编程的速度也很慢,进一步浪费了他人的时间和精力。
另一个例子是Electron已成为了跨平台桌面应用的标准。为特定目的选择Electron固然没错,但软件社区允许这种毫无性能可言的东西发展成为最佳选择却是个错误。
不要再说“不喜欢慢的软件,你可以不用啊”,因为许多东西已成为事实上的标准,你无处躲避。公司可能要求使用Microsoft Teams作为交流工具,你就不得不仅仅为发几条消息而耗费大量的内存和电池。越来越多的人愿意为Atom开发语言插件,所以在选择优秀的IDE时,Atom就成了唯一可行的选择,于是你不得不忍受它的性能。
原文地址:https://metarabbit.wordpress.com/2018/02/05/pythons-weak-performance-matters/
作者:Luis Pedro Coelho,计算生物学家。2011年卡内基·梅隆大学博士毕业,主要从事亚细胞定位分析等生物图形信息研究、以及大规模图像数据的处理,致力于生物标本图像分析中机器学习技术的应用。他是Python计算机视觉库mahotas的主要开发人员。他于1998年开始开发开源软件,2004年起从事Python开发,并为多个Python开源库贡献了代码。
译者:马晶慧
————— 推荐阅读 —————
点击图片即可阅读