Python 使用cython和h5py快速读取hdf5文件
我正在尝试加速一个python3函数,它获取一些数据,这是一个索引数组,如果它们满足某个标准,就会保存它们。我试图通过使用“cython-a script.py”来加快速度,但瓶颈似乎是h5py I/O切片数据集 我对cython比较陌生,所以我想知道是否有加快速度的方法,或者我只是受到h5py I/O的限制 以下是我试图改进的功能:Python 使用cython和h5py快速读取hdf5文件,python,cython,h5py,Python,Cython,H5py,我正在尝试加速一个python3函数,它获取一些数据,这是一个索引数组,如果它们满足某个标准,就会保存它们。我试图通过使用“cython-a script.py”来加快速度,但瓶颈似乎是h5py I/O切片数据集 我对cython比较陌生,所以我想知道是否有加快速度的方法,或者我只是受到h5py I/O的限制 以下是我试图改进的功能: import numpy as np import h5py cimport numpy as np cimport cython from libc.math
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
将numpy导入为np
进口h5py
cimport numpy作为np
西姆波特赛顿酒店
来自libc.math cimport sqrt
DTYPE64=np.int64
ctypedef np.int64\u t DTYPE64\u t
DTYPE32=np.int32
ctypedef np.int32\u t DTYPE32\u t
@cython.boundscheck(错误)
@cython.wrapparound(假)
def tag_subhalo_分支(np.ndarray[DTYPE64_t]halos_z0_treeindxs,
np.ndarray[DTYPE64_t]tree_pindx,
np.ndarray[DTYPE32_t]tree_psnapnum,
np.ndarray[DTYPE64_t]树,
np.ndarray[DTYPE64_t]tree_hsnapid,hf,
整数大小):
cdef int i
cdef双径向,前进x,前进y,前进z
cdef双主机x、主机y、主机z、主机rvir
cdef数据类型64\u t progen\u indx,progen\u haloid,主机id
cdef数据类型32\u t程序快照
cdef int j=0
cdef int size_数组=大小
cdef np.ndarray[DTYPE64\u t]反斜杠ID=np.Zero(大小数组,
dtype=DTYPE64)
对于范围内的i(0,大小\u数组):
progen_indx=树[i]]
如果进展顺利!=-1:
progen\u snap=tree\u psnapnum[progen\u indx]
progen_haloid=树[progen_indx]
而progen_indx!=-1和progen_snap!=-1:
#**这太慢了**
grp=hf['Snapshots/snap'+str(“%03d”%progen\u snap)+'/']
主机id=grp['HaloCatalog'][(progen_haloid-1),2]
# **
如果主机id!=-1:
#**这太慢了**
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]
# **
径向=0
径向+=(程序x-主机x)**2
径向+=(程序-主机)**2
径向+=(程序-主机)**2
径向=sqrt(径向)
host_rvir=grp['HaloCatalog'][(host_id-1),24]
如果径向如本文所述:,h5py
使用cython
代码与HDF5
c
代码接口。因此,您自己的cython
代码可能可以直接访问它。但我怀疑这需要更多的研究
您的代码正在使用Python接口来h5py
,而cythonizing
不会触及这一点
cython
代码最好用于低级操作,尤其是不能表示为数组操作的迭代操作。首先研究并实验numpy
示例。你正潜入游泳池最深处的赛昂
您是否尝试过仅使用Python和numpy来改进代码?乍一看,我看到了很多冗余的h5py
调用
====================
您的radial
计算访问h5py
索引6次,而它可以使用2。也许你这样写是希望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))
为什么不加载所有数据[progen\u haloid-1,:]
和数据[host\u id-1,:]
?甚至所有的数据
?我必须检查h5py
何时从直接使用文件上的数组切换到numpy
数组。在任何情况下,内存中数组的数学运算都比文件读取快得多。如本文所述:,h5py
使用cython
代码与HDF5
c
代码接口。因此,您自己的cython
代码可能可以直接访问它。但我怀疑这需要更多的研究
您的代码正在使用Python接口来h5py
,而cythonizing
不会触及这一点
cython
代码最好用于低级操作,尤其是不能表示为数组操作的迭代操作。首先研究并实验numpy
示例。你正潜入游泳池最深处的赛昂
您是否尝试过仅使用Python和numpy来改进代码?乍一看,我看到了很多冗余的h5py
调用
====================
您的radial
计算访问h5py
索引6次,而它可以使用2。也许你这样写是希望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))
为什么不加载所有数据[progen\u haloid-1,:]
和数据[host\u id-1,:]
?甚至所有的数据
?我必须检查h5py
何时从直接使用文件上的数组切换到numpy
数组。在任何情况下,内存中数组上的数学运算都比文件读取快得多。cython
可以在c
中执行操作,从而提高速度。它还可以使用自己的内存视图执行一些numpy
索引。但是它不能触摸h5py
索引。为此,它必须调用h5py
函数<代码