1、参照以下代码示例,pandas计算在纯Python代码执行耗时:47.806718587875366秒;
2、基于此代码示例修改,将其比较耗时部分的计算函数改写成Cpython语法执行耗时:3.6926722526550293秒,最终将提升10倍以上性能。
一、性能提升前(纯Python实现)
import time
import pandas as pd
import numpy as np
df = pd.DataFrame(
{
"a": np.random.randn(100000),
"b": np.random.randn(100000),
"N": np.random.randint(100, 1000, (100000)),
"x": "x",
}
)
def f(x):
return x * (x - 1)
def integrate_f(a, b, N):
s = 0
dx = (b - a) / N
for i in range(N):
s += f(a + i * dx)
return s * dx
start_time = time.time()
print(df.apply(lambda x: integrate_f(x["a"], x["b"], x["N"]), axis=1))
print(time.time() - start_time) # 耗时:47.806718587875366
二、Cpython提升pandas性能
1. 安装 Cython:
首先,确保你已经安装了 Cython。你可以通过 pip 在命令行中安装:
pip install cython
2. 创建 Cython 文件:
在 PyCharm 中创建一个新的 Python 文件,但将文件扩展名更改为 .pyx(例如 cpy.pyx)。这个文件将包含你的 Cython 代码。参考性能提升前纯python写的函数方法,我们可以注释函数变量和返回类型,也可以使用cdef和cpdef来提高性能:
# cpy.pyx
cdef double f_typed(double x) except? -2:
return x * (x - 1)
cpdef double integrate_f_typed(double a, double b, int N):
cdef int i
cdef double s, dx
s = 0
dx = (b - a) / N
for i in range(N):
s += f_typed(a + i * dx)
return s * dx
3. 创建 setup.py 文件:
为了编译 .pyx 文件,你需要一个 setup.py 文件,它使用 distutils 或 setuptools 来编译 Cython 代码。例如:
# setup.py
from setuptools import setup
from Cython.Build import cythonize
setup(
ext_modules = cythonize("cpy.pyx")
)
4. 编译 Cython 代码:
在 PyCharm 的终端(Terminal)中,运行以下命令来编译你的 Cython 代码:
python setup.py build_ext --inplace
这将生成一个 .so(在 Unix/Linux/macOS 上)或 .pyd(在 Windows 上)文件,该文件是编译后的 Cython 模块的二进制形式。
5. 在 Python 中使用 Cython 模块:
一旦你编译了 Cython 代码,你就可以像导入普通的 Python 模块一样在你的 Python 代码中导入和使用它。与最初的纯Python实现相比,用C类型注释函数的性能提高了十倍以上。例如:
# main.py
import cpy
import pandas as pd
import numpy as np
import time
df = pd.DataFrame(
{
"a": np.random.randn(100000),
"b": np.random.randn(100000),
"N": np.random.randint(100, 1000, (100000)),
"x": "x",
}
)
start_time = time.time()
# 注意:apply中的方法与纯python写法的差异
print(df.apply(lambda x: cpy.integrate_f_typed(x["a"], x["b"], x["N"]), axis=1))
print(time.time() - start_time) # 耗时:3.6926722526550293
三、总结
1、 现在你可以在 PyCharm 中运行和调试你的 Python 代码,它将调用你的 Cython 模块;
2、记住,Cython是一种编译型语言,它允许你编写接近 C 性能的代码,但仍然可以使用 Python 的语法和库;
3、在编写 Cython代码时,注意类型声明和内存管理,以最大化性能并避免常见的错误。