簡體   English   中英

如何在cython中並行化numpy操作

[英]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循環。 但是在我看來,可以對您的代碼進行許多更簡單的優化。

我建議您執行以下操作:

  1. 分析您的原始Python代碼(例如,使用line_profiler )以查看瓶頸所在。
  2. 將注意力集中在加快單線程版本的這些瓶頸上。 如果需要幫助,您應該在SO上提出一個單獨的問題。
  3. 如果優化的單線程版本仍然太慢而無法滿足您的需求,請使用joblibmultiprocessing對其進行並行化。 一旦您嘗試了所有其他可以想到的東西,並行化通常是可以達到的最后一個工具。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM