2017-10-04 89 views
0

在下面的代碼中,test_func_1大約比test_func_2慢一個數量級。對於此操作是否無法改善或甚至不能匹配numpy性能?Numba矢量化比3d陣列的numpy慢嗎?

from numba import guvectorize 
import numpy as np 

@guvectorize(['void(float64[:,:,:], float64[:], float64[:,:,:])'], '(n,o,p),(n)->(n,o,p)', nopython=True) 
def test_func_1(time_series, areas, res): 
    for i in range(areas.size): 
     area = areas[i] 
     adjusted_area = (area/10000.) ** .12 # used to adjust erosion 
     for k in range(time_series.shape[0]): 
      res[i, 0, k] = time_series[i, 0, k] * area 
      res[i, 1, k] = time_series[i, 1, k] * adjusted_area 
      res[i, 2, k] = time_series[i, 2, k] * area 
      res[i, 3, k] = time_series[i, 3, k] * adjusted_area 


def test_func_2(time_series, areas): 
    array = np.swapaxes(time_series, 0, 2) 
    array[:, :2] *= areas 
    array[:, 2:] *= (areas/10000.) ** .12 
    return array 

dummy = np.float32(np.random.randint(0, 10, (20, 5, 5000))) 
areas = np.float32(np.random.randint(0, 10, 20)) 

test_func_1(dummy, areas) 
test_func_2(dummy, areas) 
+0

我使用給定的數據集爲'test_func_2(dummy,areas)'獲得了大約80微秒的時間。這真的是你的瓶頸嗎?或者你只是想學習numba?或者你實際上在處理更大的數據? – Divakar

+0

我得到'test_func_1'大約慢了2倍。當你計算它時,你是否只計算一次(包括jit編譯時間)還是計算後續調用,這些調用會緩存編譯,並且只是函數的運行時間? – JoshAdel

+0

爲了清晰起見,它被簡化了。我打算使用類似的功能,最終會在非常大的3D陣列上被稱爲幾萬次。 – triphook

回答

3

由於@JoshAdel在評論中指出的,這裏的關鍵區別是,你numba版本分配和填充新的陣列,而numpy的是修改,代替原來的。

將適當的.copy()添加到numpy中會使其稍慢。你也可以使用你的numba版本 - 就我所知不可能使用gufunc而言,但如果你不需要gufunc提供的廣播,那麼使用常規的jit函數。

def test_func_2(time_series, areas): 
    array = np.swapaxes(time_series, 0, 2).copy() 
    array[:, :2] *= areas 
    array[:, 2:] *= (areas/10000.) ** .12 
    return array 

dummy = np.float32(np.random.randint(0, 10, (20, 5, 5000))) 
areas = np.float32(np.random.randint(0, 10, 20)) 

%timeit test_func_1(dummy, areas) 
1.21 ms ± 5.33 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each) 

%timeit test_func_2(dummy, areas) 
1.77 ms ± 15.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)