背景
本人的主力语言是 Python & JavaScript & C++;数据采集主要用 JavaScript 语言实现,后面的分析用 Python 实现。
经验上看 Python 可以解决掉我 99.9% 的问题,之所不敢说是 100%,是因为有一次我把一小部分代码用 C++ 重写后整体耗时下降 40 倍。这个也就是我后来开始重视 C++ 的原因。
前段时间 TOIBE 2022 年编程语言排名发布了, C++ 成为了 2022 年的最佳编程语言;我的第一感觉就是 “这家伙理所应当呀!”
TIOBE 排名的原文链接:https://www.tiobe.com/tiobe-index
C++ 与 Python 的协同效应
我们知道 Python 的一大应用场景就是科学计算(人工智能),为了程序可以运行的更快,人类可谓是用心良苦。
比如为特定算法设计硬件,但单单是有了硬件还不行 !Python 现阶段无法直接调用硬件,程序员还需要先用 C/C++ 开发好驱动程序,并暴露好相应的 API 给 Python 。
我遇到的多数情况都用不着设计专业的硬件,单单只是把算法用 C/C++ 重写一下,就能解决问题。
也就是说 Pythoner 一旦发现自己程序的性能不好,算法上也没有找到好的改进项,这个时候用 C++ 重写一下多数情况可以提升性能。 这正是 TIOBE 排行榜上近几年 C++ 与 Python 表现出正相关的原因。
TIOBE 排名的原文链接:https://www.tiobe.com/tiobe-index
C++ vs Python 性能测试
我之前遇到的 Python 性能问题大多数是它计算慢,当然也不排除其它人的模型主要是慢在 IO 上。一开始我也不觉得 Python 会在计算上慢多少,直到我自己在机器上分别用 C++ 和 Python 测试了一下,结果让我无语了,原来 C++ 这么强。
我当时用的是计算“斐波那契数列”的第 n 位这个来测试的,一来测试的是计算,二来测试代码也简单;所以就选择了这个(这么少的测试样本自然是不能完全证明 C++ 比 Python 快多少的,但是可以做一个大概的把握)。
我们先看测试的结论(性能上看真的是一个天一下地)。
代码如下
#/usr/bin/env python3
"""
测试 Python & C++ 这两种语言计算 斐波那契数列 的快慢。
"""
from datetime import datetime
# 导入我们手写的 C++ 代码逻辑(后面会讲)
from plugins import cppmath
def fib(n):
"""求 斐波那契数列 的第 n 位的值
Parameter:
----------
n: int
第 n 位
Return:
-------
int
返回斐波那契数列第 n 位的值
"""
if n == 1 or n == 2:
return 1
else:
return fib(n - 1) + fib(n - 2)
def main(n):
"""分别测试 C++ 和 Python 计算同一个数的耗时
"""
start = datetime.now()
res = cppmath.fib(n)
end = datetime.now()
print("C++ 计算的结果为 {} 总的耗时 {}(s)".format(res, end-start))
start = datetime.now()
res = fib(n)
end = datetime.now()
print("Python 计算的结果为 {} 总的耗时 {}(s)".format(res, end-start))
if __name__ == "__main__":
main(40)
测试结果
python3 test-fib-speed.py
C++ 计算的结果为 102334155 总的耗时 0:00:00.140350(s)
Python 计算的结果为 102334155 总的耗时 0:00:11.720886(s)
快了 80 几倍,我已经服了。
In [1]: 11.72/0.14
Out[1]: 83.71
C++ 部分的关键代码
其实算法的逻辑是一样的,只是换了一种语言,性能就能提升 80+ 倍,牛逼++!
#include <Python.h>
// 用 C++ 实现 fib 函数
int fib(int n) {
if (n == 1 || n == 2) {
return 1;
}
else {
return fib(n - 1) + fib(n - 2);
}
}
// 把 C/C++ 的一个函数包装成一个 Python 函数
static PyObject *py_fib(PyObject *self,PyObject *args)
{
int x = 0,result = 0;
PyArg_ParseTuple(args,"i",&x);
result = fib(x);
return Py_BuildValue("i",result);
}
// 定义模块要包含的函数列表
static PyMethodDef methods[] = {
{"fib", py_fib, METH_VARARGS, "fib"},
{0,0,0,0}
};
// 定义模块
static struct PyModuleDef module = {
PyModuleDef_HEAD_INIT,
"plugins",
"extend cpython",
-1,
methods
};
// 定义模块的初始化方法
PyMODINIT_FUNC PyInit_cppmath(void)
{
return PyModule_Create(&module);
}
一旦我们像上面一样完成了模块和函数的定义,Python 就能识别我们的 C++ 函数了,到时候就可以 import 进来直接调用。
C++ 学习推荐 大多数 C++ 书籍(大学教材)都是以 C++1998 年的标准编写,导致一方面还没有学完就已经过时了,另一方面用法也复杂,容易写出 Bug 。
近几年 C++ 标准越来越以人为本,它尽可能让编译器多做点事,让程序员更舒服一些。比如引入了智能指针,我再也不用怕手工分配的内存, 因为忘记释放导致内存泄漏了。引入了模块和协程 ... ... 等等一大堆好东西。这一切都在使 C++ 开发变得简单。如果现在学 C++ 的话,我首推《C++20实践入门》 + 《C++20高级编程》。
如果硬要说这两套书有什么缺点的话,就是书的作者太激进了,全书都是用 C++20 标准写的,导致有部分特性编译器没有跟上,比如 “模块”,“format” ,到时候在 GCC 和 CLANG 上编译会有问题,但是在微软的编译器上是 OK 的(微软牛逼)。
还有一本基于 C++11 标准的也值得一读,它的优点就是讲的非常细,如果想成为这门语言的专家,那一定要读一读这一本。
最后
都到这里了,是时候图穷匕见了!我这人比较 real 就直说了,我想涨粉帮忙点下关注!我的技术文章质量还可以,关注应该不亏。
“在看” + “分享” + “点赞” + “收藏” 也是我继续写下去的动力;再次感谢!!!