[英]How to parallelize the numpy operations in cython
我正在嘗試並行化以下代碼,其中包括許多numpy數組操作
#fft_fit.pyx
import cython
import numpy as np
cimport numpy as np
from cython.parallel cimport prange
from libc.stdlib cimport malloc, free
dat1 = np.genfromtxt('/home/bagchilab/Sumanta_files/fourier_ecology_sample_data_set.csv',delimiter=',')
dat = np.delete(dat1, 0, 0)
yr = np.unique(dat[:,0])
fit_dat = np.empty([1,2])
def fft_fit_yr(np.ndarray[double, ndim=1] yr, np.ndarray[double, ndim=2] dat, int yr_idx, int pix_idx):
cdef np.ndarray[double, ndim=2] yr_dat1
cdef np.ndarray[double, ndim=2] yr_dat
cdef np.ndarray[double, ndim=2] fft_dat
cdef np.ndarray[double, ndim=2] fft_imp_dat
cdef int len_yr = len(yr)
for i in prange(len_yr ,nogil=True):
with gil:
yr_dat1 = dat[dat[:,yr_idx]==yr[i]]
yr_dat = yr_dat1[~np.isnan(yr_dat1).any(axis=1)]
print "index" ,i
y_fft = np.fft.fft(yr_dat[:,pix_idx])
y_fft_abs = np.abs(y_fft)
y_fft_freq = np.fft.fftfreq(len(y_fft), 1)
x_fft = range(len(y_fft))
fft_dat = np.column_stack((y_fft, y_fft_abs))
cut_off_freq = np.percentile(y_fft_abs, 25)
imp_freq = np.array(y_fft_abs[y_fft_abs > cut_off_freq])
fft_imp_dat = np.empty((1,2))
for j in range(len(imp_freq)):
freq_dat = fft_dat[fft_dat[:, 1]==imp_freq[j]]
fft_imp_dat = np.vstack((fft_imp_dat , freq_dat[0,:]))
fft_imp_dat = np.delete(fft_imp_dat, 0, 0)
fit_dat1 = np.fft.ifft(fft_imp_dat[:,0])
fit_dat2 = np.column_stack((fit_dat1.real, [yr[i]] * len(fit_dat1)))
fit_dat = np.concatenate((fit_dat, fit_dat2), axis = 0)
我已經將以下代碼用於setup.py
####setup.py
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
setup(
cmdclass = {'build_ext': build_ext},
ext_modules = [Extension("fft_fit_yr", ["fft_fit.pyx"])]
extra_compile_args=['-fopenmp'],
extra_link_args=['-fopenmp'])]
)
但是在cython中編譯fft_fit.pyx時出現以下錯誤:
for i in prange(len_yr ,nogil=True):
target may not be a Python object as we don't have the GIL
使用prange函數時,請告訴我我哪里出了問題。 謝謝。
您不能(至少不使用Cython)。
Numpy函數在Python對象上運行,因此需要GIL ,以防止多個本機線程並行執行。 如果使用cython -a
編譯代碼,則將獲得帶注釋的HTML文件,該文件顯示在何處進行Python C-API調用(因此無法釋放GIL)。
當您的代碼中存在特定瓶頸,而使用矢量化無法輕松加速時,Cython最為有用。 如果您的代碼已經在numpy函數調用中花費了大部分時間,那么從Cython調用那些完全相同的函數將不會導致任何顯着的性能改進。 為了看到明顯的差異,您需要將部分或全部數組操作編寫為顯式for
循環。 但是在我看來,可以對您的代碼進行許多更簡單的優化。
我建議您執行以下操作:
line_profiler
)以查看瓶頸所在。 joblib
或multiprocessing
對其進行並行化。 一旦您嘗試了所有其他可以想到的東西,並行化通常是可以達到的最后一個工具。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.