python的加速方法

0 资料

1 正文

1.1 python执行原理

python执行过程:python脚本语言(.py或者cython语言(.pyx)–解释器解释–>字节码(.pyc)–虚拟机执行–>机器码(看不到,可以在cpu上跑起来)。

由于没有原生的编译时类型检查,所有的类型的检查都被移交给了运行时,执行一行Python代码很可能需要做不只一行的类型检查、边界检查,因此python比起C++等会慢很多。

python的解释器可以多种,常见的是cpython(最常用)、Ipython(基于cpython的交互式解释器)、pypy(动图编译python代码,运行速度快,与cpython有少数不同)、Jython、IronPython。

1.2 Cypthon(推荐,速度与numba接近)

Cython是一门语言,文件名以.pyx结尾。其是python的超集,即兼容python,Cython与python类似于C++与C的关系。同时Cython也是一个编译器的名称,其可将Cython语言写的pyx文件(包含.py文件)直接编译成动态库,从而获得近乎于写CXX语言的性能。

官网推荐使用setuptools (setup.py)的方法来编译.pyx/.py代码。如以下文件树,

├── os

│   └── ros_os.py

│   └── setup.py

目标是将os文件夹下的ros_os.py编译成.so动态库,因此在ros_os.py同级目录下新建一个setup.py文件。setup.py的内容如下:

from setuptools import setup
from Cython.Build import cythonize

setup(
    name='ros_os',
    ext_modules=cythonize("ros_os.py"),
    zip_safe=False,
)

然后运行指令python setup.py build_ext --inplace,则会在同级目录下生成ros_os.so动态库文件。在其他python文件中,就可以通过import导入该.so文件,实现加速。

注意,若os文件夹下有__init__.py文件,则会出错。解决方法是需要将setup.py移动到与ros_os.py最近的无__init__.py文件的文件夹下,如以下文件树所示:

├── pkg

│   ├── init.py

│   ├── os

│   │   ├── init.py

│   │   └── ros_os.py

└── setup.py

os文件夹下有__init__.py文件,显式地表示os是一个python的包,同样地,pkg下也存在__init__.py文件,因此需要将setup.py放在与pkg同级的目录下,该目录是最靠近ros_os.py的最近的且无__init__.py文件的目录。同时,修改setup.py中对ros_os.py的路径,如下:

from setuptools import setup
from Cython.Build import cythonize

setup(
    name='ros_os',
    ext_modules=cythonize("pkg/os/ros_os.py"),
    zip_safe=False,
)

在setup.py的同级目录下运行编译指令:python setup.py build_ext --inplace,则可以正确编译获得ros_os.so动态文件。

优点:加速python,并达到python加密的效果(推荐的加密手段)

缺点:需要手动编译;少数python内置属性不支持,例如__file__;

1.3 numba(传言可加速40倍左右)

numba是一个可以加速python大部分模块的库,其原理是将其修饰的函数在第一次运行时先优化翻译成机器码,而在重复运行时,则直接调用该机器码,因此达到可以媲美C和C++的速度。使用方法如下:

from numba import jit  # 从numba中导入函数jit
import random

@jit(nopython=True)   # jit,numba装饰器中的一种
def monte_carlo_pi(nsamples):
    acc = 0
    for i in range(nsamples):
        x = random.random()
        y = random.random()
        if (x ** 2 + y ** 2) < 1.0:
            acc += 1
    return 4.0 * acc / nsamples

在原始代码中加入第1行和第4行,则可以加速monte_carlo_pi模块(自动将其优化并编译成机器码)。即,要加速哪个函数,就在函数定义前面加上装饰器@jit(nopython=True)。

优点:对numpy和循环语法的加速明显;使用方便;

缺点:少量库无法加速,如pandas库;仅能安装到无法用于python2及以下版本;安装比较困难,需要装llvm编译器;

1.4 其他加速方法

  • 使用整型代替浮点型

1.5 各自加速方法的对比

代码片段对大小为128x128的二维数组求和,运行1000次时间如下:

Total cost time for func: py_func, call 1000 times: 3.803216s. 
Total cost time for func: np_func, call 1000 times: 0.343562s. 
Total cost time for func: nb_func, call 1000 times: 0.017122s. 
Total cost time for func: cy_func, call 1000 times: 0.018159s.

它们分别代表了原始Python、Numpy、Numba、Cython对应的性能。可以看出,cython与numba可有效加速python代码。其中,numba以稍微快于cython,但是numba不兼容python2,且调试困难,因此,推荐使用cython。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值