python科学计算加速

1.使用GPU

使用GPU有两种方式:numba和pycuda,可以通过这两个package和python实现CUDA程序。

1.1 numba

CUDA官方加速是通过numba来使用GPU或CPU加速,在很早以前是通过numbapro实现的,属于收费版本,后面全部整合成了numba和accelerate,而且免费开放,在Anaconda环境下已经安装了numba,只需要使用即可。使用numba的GPU加速需要进行配置。具体配置方式可查看官方文档。

Refrence

[1].numba官方地址:http://numba.pydata.org/

[2].numba官方文档:http://numba.pydata.org/doc.html

[3].numba配置CUDA的GPU:http://blog.csdn.net/u013975830/article/details/78822919

1.2 pycudapy

cuda也是提供python到gpu的接口,简单可以使用pycuda自身的接口实现,复杂的就需要自己实现cuda程序再通过pycuda实现。

Refrence

[1].CUDA和pycuda环境的配置:http://blog.csdn.net/zhouqingtaostudy/article/details/50896948

[2].pycuda的官网:https://documen.tician.de/pycuda/ https://mathema.tician.de/software/pycuda/

[3].pycuda的tutorial翻译:http://blog.cycleuser.org/pycuda-tutorial-zhong-wen-ban.html

[4].pycuda的notebook:http://nbviewer.jupyter.org/github/Kivy-CN/Duke-STA-633-CN/tree/master/已经翻译的讲座内容/Topic21_GPU_Computing/

[5].pycuda的翻译:https://zhuanlan.zhihu.com/p/32062796

2.使用C加速

python中可以使用c实现部分功能来进行加速,比如Cython,Cython也可以和numpy配合使用,来对numpy进行加速。

2.1 Cython加速

(1) 使用Cython和numpy结合 将两者结合使用可以有效的加速python中的核心代码,下面通过示例说明怎么结合。下面通过cython的形式实现一个矩阵点乘的方法,具体代码如下,文件名为multi.pyx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
from __future__ import division
cimport cython
import numpy as np
cimport numpy as np

DTYPE = np.float64
ctypedef np.float64_t DTYPE_t


@cython.boundscheck(False)
def multi_product(np.ndarray a, np.ndarray b):
"""
Parameters
----------
a: np.ndarray, the shape of (m, n)
b: np.ndarray, the shape of (m, n)
return
------
np.ndarray, return the array shape of (m, n)
"""
cdef int a_array_r = a.shape[0]
cdef int a_array_c = a.shape[1]
cdef int b_array_r = b.shape[0]
cdef int b_array_c = b.shape[1]
if a_array_r != b_array_r or a_array_c != b_array_c:
raise Exception("ValueError: operands could not be broadcast together with shapes %s %s"
%(str((a_array_r, a_array_c)), str((b_array_r, b_array_c))))
out = np.zeros((a_array_r, a_array_c))
for _r_ in range(a_array_r):
for _c_ in range(a_array_c):
out[_r_, _c_] = a[_r_, _c_] * b[_r_, _c_]
return out

创建一个setup.py的文件,类似c++中的makefile配置文件,setup.py文件内容主要时配置编译,具体代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
import numpy
from distutils.core import setup, Extension
from Cython.Distutils import build_ext

setup(
cmdclass={'build_ext': build_ext},
ext_modules=[
Extension("multi", ["multi.pyx"],
include_dirs=[numpy.get_include()])
]
)

上面setup.py文件中的include_dirs非常重要,否则在后面编译pyx文件时会出现一些错误:找不到”numpy/arrayobject.h”,因此需要在setup.py文件中将依赖的.h文件给添加上。下面通过命令进行编译即可:

1
python setup.py build_ext --inplace

编译后会生成.so文件(linux,windows下为dll文件)。后面通过python直接引用该文件,调用其中的方法即可。下面对使用cython实现的点乘方法和numpy包的multiply方法效率进行对比:

1
2
3
4
5
6
7
8
9
import timeit

print(timeit.timeit(stmt="multi.multi_product(x, y)", setup="import multi; import numpy as np; x = np.array([[1, 2, 3], [2.4, 89.0, 11]]); y = np.array([[1, 2, 3], [2.4, 89.0, 11]])", number=10000))

print(timeit.timeit(stmt="np.multiply(x, y)", setup="import numpy as np; x = np.array([[1, 2, 3], [2.4, 89.0, 11]]); y = np.array([[1, 2, 3], [2.4, 89.0, 11]])", number=10000))

# -------- output -------------------
0.03196066700184019
0.006172515997604933

效率上还是比不上numpy,主要是因为numpy在这方面做了深度优化。但是比纯python实现的方法要快很多。
Refrence

[1]Cython官方文档:http://cython.org/

[2].Cython基础教程中文版:https://moonlet.gitbooks.io/cython-document-zh_cn/content/ch1-basic_tutorial.html

[3].Cython中def, cdefcpdef区别和使用:http://notes-on-cython.readthedocs.io/en/latest/index.html

[4].Cython中def,cdef,cpdef的区别: http://www.cnblogs.com/lidyan/p/7474244.html

2.2 PyPy 加速

PyPy是用Python实现的Python解释器。

[1].用 Psyco 让 Python 运行得像 C 一样快:https://www.ibm.com/developerworks/cn/linux/sdk/python/charm-28/

2.3 numexpr加速

使用numexpr[http://numexpr.readthedocs.io/en/latest/index.html]

Refrence

[1].优化 Python 性能:PyPy、Numba 与 Cython比较:https://www.zhihu.com/question/24695645

[2].numpy的c-api接口:http://python.usyiyi.cn/documents/NumPy_v111/reference/c-api.html

[3].python中使用C代码-以numpy为例:https://segmentfault.com/a/1190000000479951

[4].python-numpy-c-extension-exampleshttps://github.com/johnnylee/python-numpy-c-extension-examples