业界传说Python平均一行代码能够顶的上几十行C/C++代码。业界还传说,C++效率能够达到Python的几十倍。
对于以上二者,笔者本来感觉也许差不多只是略夸张。笔者曾经用C++和Python分别实现了不带cache的求Fibonacci数的函数,大约C++的效率确实可以达到Python效率的几十倍,不过代码量没有几十倍,只是略多。但这个毕竟是toy programming,如果是在一个真正实用性的项目当中,C++和Python在效率以及代码量上的对比究竟几何呢?笔者做了一个实验。
大约一年多前,笔者利用过年的时间,用Python实现了一个微信欢乐斗地主的残局解答器,还写了一篇CSDN博文,详见《做一个微信欢乐斗地主之残局解答器!》, 代码见GitHub:https://github.com/FinixLei/WeChat_LandLords/tree/master/Python
时隔一年,笔者又利用今年的五一假期的业余时间,用C++11将这个残局解答器重写了一遍,新代码在GitHub的这里:https://github.com/FinixLei/WeChat_LandLords/tree/master/Cpp
期间有一些心得,记录如下。
1. 实现选型与新老程序对比
关于实现选型,鉴于C++11已经出来很久了,而且很明显,C++11的一些特性如auto等,对缩短代码量很有好处,因此C++11是不二之选。
新老程序在实现的逻辑和算法上是比较接近的,否则进行代码量和效率的对比也就没有意义了。故此,笔者没有对C++代码做特别优化。
C++11的实现虽然Fix了Python实现里的几个bug,但都是比较小的bug,并不影响正确性,只是对效率有那么一点可以忽略不计的影响。所以,原Python程序在正确性上还是比较可靠的。
但是,
关于多线程实现的选型,笔者尝试了C++11多线程和POSIX的pthread系列之后,最终还是选择了libpthread来实现多线程程序。C++11的多线程似乎是有一些坑的
,而pthread实现起来还是可以的,并不繁杂。毕竟,要做一个平台无关的语言级多线程不是那么容易。这其中,比较重要的一两个坑,笔者已经写在前一篇博客里了,参见《C++11多线程的局限》.
2. 代码量的对比
功能性代码(行) | 测试代码(行) | |
---|---|---|
C++11 | 1706 | 639 |
Python | 1215 | 289 |
从功能性代码来看, C++11比Python多了刚好40%,并不是业界传说的几十倍。
3. 效率的对比
一般的残局题目C++实现都是1秒左右给出答案,而Python也是秒级,看不太出来准确的区别。故笔者找到几个难一点的题目,以一台阿里云的双核四线程的ECS测下来,计算时间如下。
case-1 | case-2 | case-3 | |
---|---|---|---|
Python | 37.59 秒 | 152.57 秒 | 237.08 秒 |
C++11 | 2.41 秒 | 12.68 秒 | 8.99 秒 |
倍数 | 15.60 倍 | 12.03 倍 | 26.37 倍 |
值得注意的是,编译的时候需要加-O2选项以做优化。如果不加该选项,效率会差6倍左右(谢谢网友qq_24038061指出原文疏漏之处)。
测试用例如下:
case-1:
人类的牌(地主): "小王 大王 K 10 10 7 8 8 6 6"
电脑的牌(农民): "2 2 A A A 9 9 7 6 6 3 3"
case-2:
人类的牌(地主): "2 2 A Q J 9 9 6 6 4"
电脑的牌(农民): "大王 A K K Q J J 10 8 8 7 4 4"
case-3:
人类的牌(地主): "2 Q 9 7 6 6 5 5 4"
电脑的牌(农民): "K K Q J 10 9 7 6 6 4 3 3"
可见,效率是在
12-26倍
之间。
综上所述,就本项目而言,
Python写起来爽,代码量是C++11的70%左右,但效率却真的只有C++的十几分之一到几十分之一!
(完)