2016-10-07 7 views
0

私は、インデックスの配列であるデータをとり、特定の条件を満たす場合にそれらを保存するpython3関数を高速化しようとしています。私は "cython -a script.py"を使って速度を上げようとしましたが、ボトルネックはh5py I/Oスライスデータセットのようです。cythonとh5pyで素早くhdf5ファイルを読む

私はcythonには比較的新しいので、これを高速化するための方法があるのか​​、ここではh5py I/Oによって制限されているのでしょうか?ここで

は、私が改善しようとしている機能である:

import numpy as np 
import h5py 

cimport numpy as np 
cimport cython 
from libc.math cimport sqrt 

DTYPE64 = np.int64 
ctypedef np.int64_t DTYPE64_t 
DTYPE32 = np.int32 
ctypedef np.int32_t DTYPE32_t 

@cython.boundscheck(False) 
@cython.wraparound(False) 
def tag_subhalo_branch(np.ndarray[DTYPE64_t] halos_z0_treeindxs, 
         np.ndarray[DTYPE64_t] tree_pindx, 
         np.ndarray[DTYPE32_t] tree_psnapnum, 
         np.ndarray[DTYPE64_t] tree_psnapid, 
         np.ndarray[DTYPE64_t] tree_hsnapid, hf, 
         int size): 

    cdef int i 
    cdef double radial, progen_x, progen_y, progen_z 
    cdef double host_x, host_y, host_z, host_rvir 
    cdef DTYPE64_t progen_indx, progen_haloid, host_id 
    cdef DTYPE32_t progen_snap 
    cdef int j = 0 
    cdef int size_array = size 
    cdef np.ndarray[DTYPE64_t] backsplash_ids = np.zeros(size_array, 
                 dtype=DTYPE64) 


    for i in range(0, size_array): 
     progen_indx = tree_pindx[halos_z0_treeindxs[i]] 
     if progen_indx != -1: 
      progen_snap = tree_psnapnum[progen_indx] 
      progen_haloid = tree_psnapid[progen_indx] 

      while progen_indx != -1 and progen_snap != -1: 
       # ** This is slow ** 
       grp = hf['Snapshots/snap_' + str('%03d' % progen_snap) + '/'] 
       host_id = grp['HaloCatalog'][(progen_haloid - 1), 2] 
       # ** 

       if host_id != -1: 
        # ** This is slow ** 
        progen_x = grp['HaloCatalog'][(progen_haloid - 1), 6] 
        host_x = grp['HaloCatalog'][(host_id - 1), 6] 
        progen_y = grp['HaloCatalog'][(progen_haloid - 1), 7] 
        host_y = grp['HaloCatalog'][(host_id - 1), 7] 
        progen_z = grp['HaloCatalog'][(progen_haloid - 1), 8] 
        host_z = grp['HaloCatalog'][(host_id - 1), 8] 
        # ** 
        radial = 0 
        radial += (progen_x - host_x)**2 
        radial += (progen_y - host_y)**2 
        radial += (progen_z - host_z)**2 
        radial = sqrt(radial) 

        host_rvir = grp['HaloCatalog'][(host_id - 1), 24] 
        if radial <= host_rvir: 
         backsplash_ids[j] = tree_hsnapid[ 
          halos_z0_treeindxs[i]] 
         j += 1 
         break 

       # Find next progenitor information 
       progen_indx = tree_pindx[progen_indx] 
       progen_snap = tree_psnapnum[progen_indx] 
       progen_haloid = tree_psnapid[progen_indx] 
    return backsplash_ids 
+0

'cython'は' c'でアクションを実行できるときに速度を向上させます。また、 'numpy'インデックスを独自の' memoryviews 'で実行することもできます。しかし、それは 'h5py'インデックスに触れることはできません。これを行うには 'h5py'関数を呼び出さなければなりません。 'cython'は、配列操作として表現できない内部ループに最適です。 – hpaulj

答えて

1

ここで説明したように:http://api.h5py.org/h5pyHDF5cコードとインタフェースするcythonコードを使用しています。だからあなた自身のcythonコードがそれに直接アクセスできるかもしれません。しかし、私はもっと多くの研究が必要だと思う。

あなたのコードはh5pyにPythonインターフェイスを使用しています。cythonizingはそれに触れません。

cythonコードは、低レベルのアクション、特に配列操作として表現できない反復的なものに最適です。最初にnumpyの例を調べて実験してください。あなたはプールの深いところでcythonにダイビングしています。

Pythonとnumpyだけでコードを改善しようとしましたか?一見すると、冗長なh5pyコールがたくさん出てきています。それは2とによって得ることができるとき

====================

あなたradial計算がh5pyインデックスを6回アクセスたぶん、あなたはそれを書いていますcythonがnumpyよりも速く次の計算を実行することを期待していますか?

data = grp['HaloCatalog'] 
progen = data[progen_haloid-1, 6:9] 
host = data[host_id-1, 6:9] 
radial = np.sqrt((progren-host)**2).sum(axis=1)) 

なぜすべてdata[progen_haloid-1,:]data[host_id-1,:]をロードしませんか? dataのすべてh5pyがファイル上の配列を直接操作したり、配列がnumpyの配列になったりすると、私はいつ見直さなければならないでしょうか。いずれにしても、メモリ上の配列の数はファイルの読み込みよりもずっと速くなります。

+0

ありがとう前にNumpyを試してみましたが、そのテクニックでInput呼び出しを減らすことは考えていませんでした。しかし、それはまだ少し遅いです、多分最も良いことは、タスクを分けるためにいくつかのMPI形式を使用することです? –

関連する問題