2014-05-14 99 views
4

我已经编译numpy 1.6.2和scipy与MKL希望有更好的性能。 目前我有一个很大程度上依赖于np.einsum()的代码,并且有人告诉我说,Einsum对于MKL并不好,因为几乎没有矢量化。 =( 所以我正在考虑用np.dot()和slicing重写我的一些代码,只是为了能够获得一些多核心加速。 我真的很喜欢np.einsum()的简单性和可读性是好 无论如何,例如,我有以下形式的多维矩阵乘法:Numpy np.einsum数组乘法使用多核

np.einsum('mi,mnijqk->njqk',A,B) 

那么,如何改变这样的事情,或其他3,4和5次维数组中的乘法np.dot()高效MKL操作?

我会广告更多信息: 我正在计算该等式:

enter image description here

这样做的,我使用的代码:

np.einsum('mn,mni,nij,nik,mi->njk',a,np.exp(b[:,:,np.newaxis]*U[np.newaxis,:,:]),P,P,X) 

这不是那么快,在用Cython编码一样的东西是快5倍倍:

#STACKOVERFLOW QUESTION: 
from __future__ import division 
import numpy as np 
cimport numpy as np 
cimport cython 

cdef extern from "math.h": 
    double exp(double x) 


DTYPE = np.float 

ctypedef np.float_t DTYPE_t 
@cython.boundscheck(False) # turn of bounds-checking for entire function 
def cython_DX_h(np.ndarray[DTYPE_t, ndim=3] P, np.ndarray[DTYPE_t, ndim=1] a, np.ndarray[DTYPE_t, ndim=1] b, np.ndarray[DTYPE_t, ndim=2] U, np.ndarray[DTYPE_t, ndim=2] X, int I, int M): 
    assert P.dtype == DTYPE and a.dtype == DTYPE and b.dtype == DTYPE and U.dtype == DTYPE and X.dtype == DTYPE 

cdef np.ndarray[DTYPE_t,ndim=3] DX_h=np.zeros((N,I,I),dtype=DTYPE) 
cdef unsigned int j,n,k,m,i 
for n in range(N): 
    for j in range(I): 
     for k in range(I): 
      aux=0 
      for m in range(N): 
       for i in range(I): 
        aux+=a[m,n]*exp(b[m,n]*U[n,i])*P[n,i,j]*P[n,i,k]*X[m,i] 
      DX_h[n,j,k]=aux 
return DX_h 

是否有在纯Python中用cython的性能来做到这一点? (我还没有能够找出如何tensordot这个方程) 在这个cython代码中,无法做到prange,很多gil和nogil错误。

+0

我不知道np.dot支持多个处理器。你能告诉我你是如何得到这个工作的吗? – Magellan88

+0

@ Magellan88它取决于您要链接的BLAS库。其中一些支持多核。 – Midnighter

+0

我有英特尔MKL编译numpy – tcapelle

回答

4

或者,你可以使用numpy.tensordot()

np.tensordot(A, B, axes=[[0, 1], [0, 2]]) 

这也将采用多个内核,像numpy.dot()

+0

tensordot和艾尔莎姆一样灵活吗? – tcapelle

+0

@ tcapelle。我相信'einsum()'更灵活([在这种情况下](http://stackoverflow.com/a/23592642/832621)),但对于我见过'tensordot()'的大多数情况,适用。如果你需要一次乘以两个以上的数组,你可能需要'einsum()'... –

+0

正在尝试使用cython prange来做这件事只需要5个工作日,但还没有得到它的工作呢= P – tcapelle