2017-02-16 6 views
0

地球物理データを含む大きな行列(形状:2e6,6)があります。変数を割り当てるために行列内の値を検索する前に、私は3 forループを持っています。性能の向上python行列

私の最初の解決策はnp.whereです。それはあまりにも遅いです!パフォーマンスを向上させるために別のforループを使用するにはit would be betterを読んでいます。しかし、私が思いついたコードは少し遅いです。

誰かがパフォーマンスを改善する方法を知っていますか?

第一溶液(np.where

for lat in LATS: 
    for lon in LONS: 
     for depth in range(1,401,1): 

      node_point_line = matrix[np.where((matrix[:,0]==lat) * (matrix[:,1]==lon) * (matrix[:,2]==depth))][0] 

      var1 = node_point_line[3] 
      var2 = node_point_line[4] 
      var3 = node_point_line[5] 
      ... 

第二の溶液(余分forループ)

再び
for lat in LATS: 
    for lon in LONS: 
     for depth in range(1,401,1): 

      matrix_flat = matrix.flatten() 
      for i in range(len(matrix_flat)): 
       if matrix_flat[i]==lat and matrix_flat[i+1]==lon and matrix_flat[i+2]==depth: 
        var1 = matrix_flat[i+3] 
        var2 = matrix_flat[i+4] 
        var3 = matrix_flat[i+5] 
        ... 

、両方のソリューションは遅すぎます。私はFortranやC++を避ける(私はそれが速いことを知っている)。助言がありますか?

+0

によってそれは 'WHERE'が遅いということはあまりありませんが、あなたはそれを何回もやっています。あなたは3つのレベルを反復しています。あなたは 'var1、var2、var3'で何をしていますか? – hpaulj

+0

これらの変数を使用して、各LAT/LONポイントの深度積分を計算します。 – Johngoldenboy

+0

@Johngoldenboyは、[XY問題](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)があるようです:あなたはアルゴの特定の部分を最適化するように頼みます(ルックアップ)大きな問題を解決しようとしています。積分を計算するアルゴリズムの高速化を求める別の質問(おそらく[CS](http://cs.stackexchange.com/)のウェブサイト)を開くことをお勧めします。私はあなたがしていることが極端に最適ではないと思っていますが、あなたが何をしようとしているのか分かりません。 – yeputons

答えて

0

LATSLONSの配列の大きさはどれくらいですか?それらが1つの要素であっても、あなたのプログラムはおよそ1*1*400*1e6*3 ~ 1.2e9の操作を実行する必要があります。 C++で適切に実装されていても、それは1秒以上かかることがあります。

アルゴリズムを最適化する必要があると思います。あなたがしようとしていることは本当にはっきりしていませんが、あなたのLATSリストの緯度と、LONSリストの経度と1から400の間の経度を持つ行列を見つけることを試みていると思います。ループの外部ループのマトリックスに沿って実行し、3つの条件がすべて満たされていることを確認します。その後、緯度のリストをsetの緯度で置き換えることができ、setルックアップはリストのルックアップよりもはるかに高速です。

+0

深度積分を計算する必要があります。これは、var1からvar3を使用します。 LATとLONの両方のサイズは〜100ですが、どちらもすでにリストです(set(matrix [;、1]))。私のforループを再編成するのは正しいかもしれません。 – Johngoldenboy

+0

両方の配列が100の長さの場合、操作量は膨大です: '100 * 100 * 400 * 1e6 * 3〜1e13'です。ハードウェアや最適化によっては数日ではなく数時間です。 – yeputons

+0

正確です。だから私はそれを最適化する必要があります。 – Johngoldenboy

0

数値を指定すると、データ配列lexsortだけで合理的に効率的です。これは、最初に2秒間投資され、where文がすべて削除されます。

order = np.lexsort([matrix.T][2::-1] # takes < 2 sec 
sorted = matrix[order, :] 

data_per_lat = np.split(sorted, sorted[:, 0].searchsorted(LATS[1:], axis=0) 
for lat, dpla in zip(LATS, data_per_lat): 
    data_per_lon = np.split(dpla, dpla[:, 1].searchsorted[LONS[1:], axis=0) 
    for lon, dplo in zip(LONS, data_per_lon): 
     depth, var1, var2, var3 = dplo.T[2:] 
     # the variables are now vectors, containing all data matching lon and lat sorted by depth 
0

さて、あなたがより速くあなたのループを行いますベクトル化プロセス、とあなたの出発行列を圧縮することができます。

コードスニペットはLATSLONSがソートされていることを前提としています。

それからちょうど forループのいずれか matrix_maskedオーバー nditerにより、(複雑な)
DPTH=np.arange(1,401,1) 
mask=np.in1d(matrix[:,0],LATS) * np.in1d(matrix[:,1],LONS) * np.in1d(matrix[:,2],DPTH) 
matrix_masked=matrix[mask] 

または

for i in range(matrix_masked.shape[0]): 
    var1 = matrix_masked[i,3] 
    . . . 
関連する問題