2014-02-21 63 views
0

下面的代碼顯示迭代器比numpy.arrays快得多(除非我做錯了什麼)。向量數學 - numpy vs迭代器

import numpy as np 
import itertools 
import time 

dim = 10000 
arrays = [np.array((1, 2, 3)) for x in range(dim)] 
iterators = [iter((1, 2, 3)) for x in range(dim)] 

t_array = time.time() 
print(sum(arrays)) 
print(time.time() - t_array) 

# [10000 20000 30000] 
# 0.016389131546020508 


t_iterators = time.time() 
print(list(sum(x) for x in zip(*iterators))) 
print(time.time() - t_iterators) 

# [10000, 20000, 30000] 
# 0.0011029243469238281 

而且迭代器版本不僅適用於迭代器,還適用於np.arrays,列表或元組。

因此,這是客觀問題的地方,我猜想有一個客觀的原因,numpy常常被用於這種事情(基於我在互聯網上看到的)。

這是什麼原因?或者我在做一些客觀錯誤的事情?

+0

'numpy'向量可以存儲在內存中用於進一步計算,而迭代器不能,值將消失,如果沒有存儲在某處 – simonzack

+0

高度相關:http://stackoverflow.com/questions/16819261/why-is- numpy的陣列此結果有時-非常慢。這可能是重複的... – Hooked

回答

2

我會說你做錯了,但這是一個解釋的問題,並取決於你正在解決的問題的細節。

對於呈現的情況,您將存儲一個二維numpy數組作爲numpy數組列表,然後使用「列表處理」例程。這規避了numpy內的一些優點/優化。

下面給出了在ipython中運行的一個稍微修改過的版本(不運行%pylab)。注意在這個例子中,你沒有使用itertools,但是內置的iter()函數。

import numpy as np 

dim = 10000 
arrays = [np.array((1, 2, 3)) for x in range(dim)] 
iterators = [iter((1, 2, 3)) for x in range(dim)] 

%timeit sum(arrays) 
10 loops, best of 3: 20.8 ms per loop 

%timeit list(sum(x) for x in zip(*iterators)) 
1000 loops, best of 3: 468 µs per loop 

[根據下面的評論編輯。]

所以迭代器看起來很棒,但他們有他們只能使用一次的限制;在我們重複它們之後,它們現在是「空的」。所以使用%timeit的正確測試將是每次重新創建迭代器。

def iter_test() : 
    iterators = [iter((1, 2, 3)) for x in range(dim)] 
    return list(sum(x) for x in zip(*iterators)) 

%timeit iter_test() 
100 loops, best of 3: 4.06 ms per loop 

現在我們看到它(僅)大約比循環數組快5倍。

在純numpy的我反而做了以下(二維陣列可以通過多種方式來創建)

nparrays=np.asarray(arrays) 
%timeit np.sum(nparrays,axis=0) 
1000 loops, best of 3: 279 µs per loop 

所以這快得多,因爲它應該是。

+1

我認爲你搞砸了迭代器版本的時機。迭代器在第一次運行後被消耗,所有後來的運行都會計算出空的總和。 – user2357112

+1

@ user2357112好點,你當然是對的。我已經更新了答案。結果現在更有意義。 –

3

的問題是這樣的:

arrays = [np.array((1, 2, 3)) for x in range(dim)] 

不是數組,並且該:

sum(arrays) 

不是numpy的操作。

比較定時陣列的列表,並內置sum

>>> timeit.timeit('sum(arrays)', 'from __main__ import arrays', number=1000) 
16.348400657162813 

給你一個二維數組和numpy.sum得到什麼:

>>> actual_array = numpy.array(arrays) 
>>> timeit.timeit('numpy.sum(actual_array, axis=0)', 'from __main__ import actua 
l_array; import numpy', number=1000) 
0.20679712685881668 

80倍的改進。它比迭代器版本低5倍。如果你打算使用NumPy,你需要儘可能多地保留NumPy的工作。