Python vs MATLAB performance on algorithm

前端 未结 1 1027
佛祖请我去吃肉
佛祖请我去吃肉 2020-12-12 02:03

I have a performance question about two bits of code. One is implemented in python and one in MATLAB. The code calculates the sample entropy of a time series (which sounds

相关标签:
1条回答
  • 2020-12-12 02:37

    As said in the comments, Matlab uses a jit-compiler by default Python doesn't. In Python you could use Numba to do quite the same.

    Your code with slight modifications

    import numba as nb
    import numpy as np
    import time
    
    @nb.jit(fastmath=True,error_model='numpy')
    def sample_entropy(time_series, sample_length, tolerance=None):
        """Calculate and return Sample Entropy of the given time series.
        Distance between two vectors defined as Euclidean distance and can
        be changed in future releases
        Args:
            time_series: Vector or string of the sample data
            sample_length: Number of sequential points of the time series
            tolerance: Tolerance (default = 0.1...0.2 * std(time_series))
        Returns:
            Vector containing Sample Entropy (float)
        References:
            [1] http://en.wikipedia.org/wiki/Sample_Entropy
            [2] http://physionet.incor.usp.br/physiotools/sampen/
            [3] Madalena Costa, Ary Goldberger, CK Peng. Multiscale entropy analysis
                of biological signals
        """
        if tolerance is None:
            tolerance = 0.1 * np.std(time_series)
    
        n = len(time_series)
        prev = np.zeros(n)
        curr = np.zeros(n)
        A = np.zeros((sample_length))  # number of matches for m = [1,...,template_length - 1]
        B = np.zeros((sample_length))  # number of matches for m = [1,...,template_length]
    
        for i in range(n - 1):
            nj = n - i - 1
            ts1 = time_series[i]
            for jj in range(nj):
                j = jj + i + 1
                if abs(time_series[j] - ts1) < tolerance:  # distance between two vectors
                    curr[jj] = prev[jj] + 1
                    temp_ts_length = min(sample_length, curr[jj])
                    for m in range(int(temp_ts_length)):
                        A[m] += 1
                        if j < n - 1:
                            B[m] += 1
                else:
                    curr[jj] = 0
            for j in range(nj):
                prev[j] = curr[j]
    
        N = n * (n - 1) // 2
    
        B2=np.empty(sample_length)
        B2[0]=N
        B2[1:]=B[:sample_length - 1]
        similarity_ratio = A / B2
        se = - np.log(similarity_ratio)
        return se
    

    Timings

    a = np.random.rand(1, 95000)[0] #Python
    a = rand(1, 95000) #Matlab
    Python 3.6, Numba 0.40dev, Matlab 2016b, Core i5-3210M
    
    Python:       487s
    Python+Numba: 12.2s
    Matlab:       71.1s
    
    0 讨论(0)
提交回复
热议问题