大規模な数値(N〜10^3)の粒子間の対の電磁気的相互作用を計算し、その結果をNxN complex128 ndarrayに保存するPython関数を書いています。それは実行されますが、N = 900の場合には約40秒かかって大きなプログラムの中で最も遅いものです[修正]。元のコードは次のようになります。Cythonのスピードアップが期待通りではありません
import numpy as np
def interaction(s,alpha,kprop): # s is an Nx3 real array
# alpha is complex
# kprop is float
ndipoles = s.shape[0]
Amat = np.zeros((ndipoles,3, ndipoles, 3), dtype=np.complex128)
I = np.array([[1,0,0],[0,1,0],[0,0,1]])
im = complex(0,1)
k2 = kprop*kprop
for i in range(ndipoles):
xi = s[i,:]
for j in range(ndipoles):
if i != j:
xj = s[j,:]
dx = xi-xj
R = np.sqrt(dx.dot(dx))
n = dx/R
kR = kprop*R
kR2 = kR*kR
A = ((1./kR2) - im/kR)
nxn = np.outer(n, n)
nxn = (3*A-1)*nxn + (1-A)*I
nxn *= -alpha*(k2*np.exp(im*kR))/R
else:
nxn = I
Amat[i,:,j,:] = nxn
return(Amat.reshape((3*ndipoles,3*ndipoles)))
私は以前にCythonを使用したことがありませんでしたが、それは物事をスピードアップするために私の努力に開始するには良い場所のように思えたので、私はかなり盲目的に私がオンラインで見られる技術を適応チュートリアル。私はいくつかのスピードアップ(30秒対40秒)が、私が期待したほど劇的ではないので、私は何か間違っているか、重要なステップを欠いているのだろうかと思っています。以下は、上記のルーチンをcythonizingで私の最高の試みです:
import numpy as np
cimport numpy as np
DTYPE = np.complex128
ctypedef np.complex128_t DTYPE_t
def interaction(np.ndarray s, DTYPE_t alpha, float kprop):
cdef float k2 = kprop*kprop
cdef int i,j
cdef np.ndarray xi, xj, dx, n, nxn
cdef float R, kR, kR2
cdef DTYPE_t A
cdef int ndipoles = s.shape[0]
cdef np.ndarray Amat = np.zeros((ndipoles,3, ndipoles, 3), dtype=DTYPE)
cdef np.ndarray I = np.array([[1,0,0],[0,1,0],[0,0,1]])
cdef DTYPE_t im = complex(0,1)
for i in range(ndipoles):
xi = s[i,:]
for j in range(ndipoles):
if i != j:
xj = s[j,:]
dx = xi-xj
R = np.sqrt(dx.dot(dx))
n = dx/R
kR = kprop*R
kR2 = kR*kR
A = ((1./kR2) - im/kR)
nxn = np.outer(n, n)
nxn = (3*A-1)*nxn + (1-A)*I
nxn *= -alpha*(k2*np.exp(im*kR))/R
else:
nxn = I
Amat[i,:,j,:] = nxn
return(Amat.reshape((3*ndipoles,3*ndipoles)))
NumpyはCライブラリです。 BLASを使って代数を行うので、かなり高速です。私はcython内部の仕組みを実際に理解していませんが、すでにCコードであることが分かりました。スピードの向上は何か「numpyではない」です。 –
ネストされたループ内の行単位の操作で十分にPythonインタプリタを直接呼び出す必要があり、Numpyに比べてこれらの行が支配的な可能性が高いと想定しましたが、おそらくそうではありませんか? –
コンパイラが配列内の型を認識できるようにnumpy配列を入力できます。しかし、どのくらいの違いがあるかわからない。 Pythonコードでプロファイラを実行して、実際に速度を失っている場所を確認することができます。ほとんどの時間がnumpyルーチンで費やされていると、cythonを使用することで多くの利益を得ることはできません。 – cel