Cython比纯Python要稍快或慢一些
  我使用几种技术( NumPy , Weave和Cython )来执行Python性能基准测试。  代码基本上在数学上做的是C = AB ,其中A,B和C是N x N矩阵( 注意:这是一个矩阵乘积而不是单元乘法)。 
我写了5个不同的代码实现:
我的期望是实现2到5将比实现1快得多。然而,我的结果表明不然。 这些是我相对于纯Python实现的标准化加速结果:
我对NumPy的表现非常满意,但是我对Weave的表现不太热情,而Cython的表现让我哭了。 我的整个代码分为两个文件。 一切都是自动的,你只需要运行第一个文件来查看所有结果。 有人可以通过指出我能做些什么来获得更好的结果来帮助我吗?
matmul.py:
import time
import numpy as np
from scipy import weave
from scipy.weave import converters
import pyximport
pyximport.install()
import cython_matmul as cml
def python_list_matmul(A, B):
    C = np.zeros(A.shape, dtype=float).tolist()
    A = A.tolist()
    B = B.tolist()
    for k in xrange(len(A)):
        for i in xrange(len(A)):
            for j in xrange(len(A)):
                C[i][k] += A[i][j] * B[j][k]
    return C
def numpy_array_matmul(A, B):
    return np.dot(A, B)
def weave_inline_matmul(A, B):
    code = """
       int i, j, k;
       for (k = 0; k < N; ++k)
       {
           for (i = 0; i < N; ++i)
           {
               for (j = 0; j < N; ++j)
               {
                   C(i, k) += A(i, j) * B(j, k);
               }
           }
       }
       """
    C = np.zeros(A.shape, dtype=float)
    weave.inline(code, ['A', 'B', 'C', 'N'], type_converters=converters.blitz, compiler='gcc')
    return C
N = 100
A = np.random.rand(N, N)
B = np.random.rand(N, N)
function = []
function.append([python_list_matmul, 'python_list'])
function.append([numpy_array_matmul, 'numpy_array'])
function.append([weave_inline_matmul, 'weave_inline'])
function.append([cml.cython_list_matmul, 'cython_list'])
function.append([cml.cython_array_matmul, 'cython_array'])
t = []
for i in xrange(len(function)):
    t1 = time.time()
    C = function[i][0](A, B)
    t2 = time.time()
    t.append(t2 - t1)
    print function[i][1] + ' t: ' + '{:10.6f}'.format(t[0] / t[-1])
cython_matmul.pyx:
import numpy as np
cimport numpy as np
import cython
cimport cython
DTYPE = np.float
ctypedef np.float_t DTYPE_t
@cython.boundscheck(False)
@cython.wraparound(False)
@cython.nonecheck(False)
cpdef cython_list_matmul(A, B):
    cdef int i, j, k
    cdef int N = len(A)
    A = A.tolist()
    B = B.tolist()
    C = np.zeros([N, N]).tolist()
    for k in xrange(N):
        for i in xrange(N):
            for j in xrange(N):
                C[i][k] += A[i][j] * B[j][k]
    return C
@cython.boundscheck(False)
@cython.wraparound(False)
@cython.nonecheck(False)
cpdef cython_array_matmul(np.ndarray[DTYPE_t, ndim=2] A, np.ndarray[DTYPE_t, ndim=2] B):
    cdef int i, j, k, N = A.shape[0]
    cdef np.ndarray[DTYPE_t, ndim=2] C = np.zeros([N, N], dtype=DTYPE)
    for k in xrange(N):
        for i in xrange(N):
            for j in xrange(N):
                C[i][k] += A[i][j] * B[j][k]
    return C
  Python列表和高性能数学是不兼容的,忘记了cython_list_matmul 。 
  您的cython_array_matmul唯一的问题是不正确的索引使用。  它应该是 
C[i,k] += A[i,j] * B[j,k]
这就是numpy数组在Python中的索引方式,这就是Cython优化的语法。 有了这个改变,你应该得到不错的表现。
  Cython的注释功能对于发现像这样的优化问题非常有用。  你可能注意到A[i][j]产生大量的Python API调用,而A[i,j]产生任何东西。 
  另外,如果您手动初始化所有条目,则np.empty比np.zeros更合适。 
上一篇: Cython either marginally faster or slower than pure Python
