2017-06-13 6 views
0

私はPythonで行列を構築するときにいくつか問題があります。 各要素にループがあり、each element A_{ij}は図のような形をしています。ここでxはq要素の配列です(次のコードではxiで示されます)。Python:この行列を構築する際にループを回避し、行列の行列式をより速く計算するにはどうすればよいですか?

以下のコードを試しましたが、時間がかかりすぎます。私はそれがループの数のせいだと思うので、私はそれを2つの行列の積として見ていますが、ラムダは2つの次元を持っているので動作しませんでした。

これらのコードは機能として表示され、何度も使用されるため、高速化する方法はありますか?大変ありがとうございます!

def lambdak(i,j,alpha,rho): 
    return math.pi * alpha**2 * rho * math.exp(-math.pi**2 * alpha**2 *(i**2 + j**2)) 
def phik(i,j,x,alpha,rho): 
    return cmath.exp(2 * math.pi * 1j * (i*x[0] + j*x[1])) 
alpha = 0.5 
rho = 50 
num = 30 
x = np.random.uniform(-0.5,0.5,num) 
y = np.random.uniform(-0.5,0.5,num) 
xi = np.zeros((num,3)) 
for i in range(num): 
    xi[i] = np.array([x[i], y[i], 0]) 
q = len(xi) 
A = [[np.sum(list(map(lambda j: 
        np.sum(list(map(lambda i: 
            lambdak(i,j,alpha,rho)/(1-lambdak(i,j,alpha,rho))* phik(i,j,xi[x]-xi[y],alpha,rho), 
            range(-N,N+1)))), 
        range(-N,N+1)))) for x in range(q)] for y in range(q)] 
a = np.linalg.inv(A) 
+0

コードを調べるだけで、いくつかの提案をすることができます。 1)コンピューティングlambdak(i、j、alpha、rho)を別の関数で移動し、2D配列に格納することができます。 qごとに再計算する必要はありません。 2)また、このコードを並列化すると、それぞれの値を独立して計算できますが、PythonにはGILの制限があります。基本的には、たとえPythonでマルチスレッド化を実装しても、重要なspeedup.Butを見ることはありませんが、キャッシュのような微妙な最適化があります。 – skippy

+0

@skippy thxそんなにあなたの答えに!私は最初の点を試してみましょう! –

+0

@skippyしかし、あなたの2番目のポイントはもう少し説明できますか?私は "キャッシュ"を見てきましたが、私はそれに慣れていないので、私は完全にXOを失っています –

答えて

0

あなたが疑うように、パフォーマンスが悪いのはあなたのループです。ループ内でnp.sumと呼んでいるので、私はあなたがnumpyを使用していると仮定します。そのトリックは、ループを内側に回し、より大きな構造(すなわち、行列)をnumpy関数に渡すことです。

これを行うと、パフォーマンスが大幅に向上します。ここ

import numpy as np 

def lambdak(i,j,alpha,rho): 
    return np.pi * alpha**2 * rho * np.exp(-math.pi**2 * alpha**2 *(i**2 + j**2)) 

def phik(i,j,x,alpha,rho): 
    return np.exp(2 * np.pi * 1j * (i*x[:, :, 0] + j*x[:, :, 1])) 

alpha = 0.5 
rho = 50 
num = 30 
x = np.random.uniform(-0.5,0.5,num) 
y = np.random.uniform(-0.5,0.5,num) 
xi = np.zeros((num,3)) 
for i in range(num): 
    xi[i] = np.array([x[i], y[i], 0]) 

X = np.arange(num).reshape(1,num) 
Y = np.arange(num).reshape(num,1) 

xi_diff = xi[X] - xi[Y] 

N = 30 

A = np.sum(map(lambda j: 
       np.sum(map(lambda i: 
         lambdak(i,j,alpha,rho)/(1-lambdak(i,j,alpha,rho))* phik(i,j,xi_diff,alpha,rho), 
         range(-N,N+1)), 0), 
        range(-N,N+1)), 0) 

a = np.linalg.inv(A) 

外側のループはnumpy機能に全体として渡される行列、に変換される:上記のコードは、に変更することができます。さらに、私はxi_diffを事前に計算しています。なぜなら、各呼び出しで構造体全体が渡されるからです(たとえ部品がphik()によって使用されたとしても)。

これは劇的なスピードアップをもたらします。しかし、計算の数値安定性が影響を受ける可能性があり、2つのアプローチの出力を比較すると、約0.1%の差があります。うまくいけば、これはOKです。

関連する問題