2016-04-30 34 views
9

我有以下兩個功能:不同的結果與量化代碼標準循環中numpy的

def loop(x): 
    a = np.zeros(10) 
    for i1 in range(10): 
     for i2 in range(10): 
      a[i1] += np.sin(x[i2] - x[i1]) 
    return a 

def vectorized(x):  
    b = np.zeros(10) 
    for i1 in range(10): 
     b += np.sin(np.roll(x, i1) - x) 
    return b 

然而,當我運行這兩個,我發現他們的結果略有不同:

x = np.arange(10) 
a, b = loop(x), vectorized(x) 
print b - a 

我得到:

[ 2.22044605e-16 0.00000000e+00 0.00000000e+00 6.66133815e-16 
    -2.22044605e-16 2.22044605e-16 0.00000000e+00 2.22044605e-16 
    2.22044605e-16 2.22044605e-16] 

這是非常小的,但在我的情況下,影響模擬。如果我從函數中刪除np.sin,則差異消失。或者,如果對x使用np.float32,差異也會消失,但這是由使用float64的解算器解決的頌歌的一部分。有沒有辦法解決這種差異?

+10

不幸的是,當你重新排序操作,比如你做了,就很難(不可能?)儘量將差別從舍入誤差的量級進入。如果這實際上在最終解決方案中存在顯着差異,那麼您需要開始問自己,如果您需要選擇不太敏感的ODE解算器(或者您嘗試解決的系統展現混沌行爲,這使得某些類型的建模不可能) – mgilson

回答

6

這是因爲您沒有按照相同的順序進行操作。

對於等效的完全向量化解決方案,請執行c=sin(add.outer(x,-x))).sum(axis=0)

In [8]: (c==loop(x)).all() 
Out[8]: True 

與您共贏矢量化的全愛維穩特:

In [9]: %timeit loop(x) 
1000 loops, best of 3: 750 µs per loop 

In [10]: %timeit vectorized(x) 
1000 loops, best of 3: 347 µs per loop 

In [11]: %timeit sin(x[:,None]-x).sum(axis=0) 
10000 loops, best of 3: 46 µs per loop