2017-08-07 73 views
1

我發現我的模擬瓶頸之一是從泊松分佈產生的隨機數。我原來的代碼是這樣的Numba和隨機數從泊松分佈

import numpy as np 
#Generating some data. In the actual code this comes from the previous 
#steps in the simulation. But this gives an example of the type of data 
n = 5000000 
pop_n = np.array([range(500000)]) 

pop_n[:] = np.random.poisson(lam=n*pop_n/np.sum(pop_n)) 

現在,我讀到numba可以非常簡單地提高速度。我定義了功能

from numba import jit 

@jit() 
def poisson(n, pop_n, np=np): 
    return np.random.poisson(lam=n*pop_n/np.sum(pop_n)) 

這個確實運行得比原來快。不過,我嘗試走得更遠:)當我寫

@jit(nopython=True) 
def poisson(n, pop_n, np=np): 
    return np.random.poisson(lam=n*pop_n/np.sum(pop_n)) 

Failed at nopython (nopython frontend) 
Invalid usage of Function(np.random.poisson) with parameters  (array(float64, 1d, C)) 
Known signatures: 
* (float64,) -> int64 
*() -> int64 
* parameterized 

一些問題:爲什麼是這樣的錯誤發生,如何解決它。

有更好的優化嗎?

+0

看起來Numba還不支持從任何np.random函數返回數組。您應該首先設置一個指定其項目類型的空數組,然後才能添加值。看看這裏的例子https://github.com/numba/numba/issues/1596 –

+2

我沒有看到任何實際的原因,爲什麼這個功能應該更快。 'np.random.poisson'已經在C中實現了。在另一個編譯函數中包裝它最多會被編譯器優化,最壞的情況是會導致開銷。 – kazemakase

+0

@kazemakase pop_n上的操作怎麼樣?它的數組除以它的總和? –

回答

2

Numba不支持數組作爲lam參數np.random.poisson,所以你要自己做循環:

import numba as nb 
import numpy as np 

@nb.njit 
def poisson(n, pop_n): 
    res = np.empty_like(pop_n) 
    pop_n_sum = np.sum(pop_n) 
    for idx, item in enumerate(range(pop_n.shape[0])): 
     res[idx] = np.random.poisson(n*pop_n[idx]/pop_n_sum) 
    return res 

n = 5000000 
pop_n = np.array(list(range(1, 500000)), dtype=float) 
poisson(n, pop_n) 

但根據我的計時,這是一樣快,使用純NumPy的:

%timeit poisson(n, pop_n) 
# 203 ms ± 1.79 ms per loop (mean ± std. dev. of 7 runs, 10 loops each) 
%timeit np.random.poisson(lam=n*pop_n/np.sum(pop_n)) 
# 203 ms ± 3.97 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) 

這是因爲,即使Numba支持np.random.poisson和喜歡np.sum這些功能僅支持爲方便其實並不以加快代碼(多)。它可能可以避免函數調用的開銷,但它只會在純Python中調用np.random.poisson一次,並不多(並且與創建50萬個隨機數相比,完全可以忽略不計)。如果你想加快循環,你不能用純NumPy的做,但你不應該指望numba(或其他東西)可以以相當於NumPy的功能提供了重要的加速

Numba是極快的。如果很容易讓它們變得更快 - 那麼NumPy的開發者也會更快。 :)

+1

作爲其他人試圖加快隨機數生成的額外我剛剛發現random_intel,它似乎運行得比基地numpy快得多 –

+0

@DiogoSantos你的意思是什麼'random_intel'?我找不到有關該功能的任何文檔。你有鏈接嗎?這可能是非常有用的:) – MSeifert

+0

這是一個非常模糊的評論。我在談論python-intel。隨機數字生成的基準可以在[這裏]找到(https://software.intel.com/zh-cn/blogs/2016/06/15/faster-random-number-generation-in-intel-distribution-for -蟒蛇) –