2015-01-21 17 views
5

Bir 2B dizisi oluşturmak için her bir sayıyı daha büyük bir sırayla küçük bir sırayla küçük bir sırayla çoğaltan aşağıdaki iki işlevi göz önünde bulundurun ve sonra tüm değerleri iki katına çıkarın. dizi. noloop(), 2B numpy dizilerinin doğrudan çarpımını kullanır ve sonucu döndürür, loop() ise arr1 üzerinden yineleme yapmak için bir döngü kullanır ve bir çıkış dizisi oluşturur.2B dizi çarpımı için döngülerden neden daha hızlıdır?

import numpy as np 

arr1 = np.random.rand(100, 1) 
arr2 = np.random.rand(1, 100000) 

def noloop(): 
    return (arr1*arr2)*2 

def loop(): 
    out = np.empty((arr1.size, arr2.size)) 
    for i in range(arr1.size): 
     tmp = (arr1[i]*arr2)*2 
     out[i] = tmp.reshape(tmp.size) 
    return out 

ben çok daha hızlı bile tekrarlamalar az sayıda için olması noloop beklenen, ancak dizi yukarıda boyutları için, loop aslında hızlıdır:

>>> %timeit noloop() 
10 loops, best of 3: 64.7 ms per loop 
>>> %timeit loop() 
10 loops, best of 3: 41.6 ms per loop 

Ve ilginçtir, ben ikisinde de *2 kaldırırsanız fonksiyonlar, noloop sadece biraz daha hızlıdır, ancak:

>>> %timeit noloop() 
10 loops, best of 3: 29.4 ms per loop 
>>> %timeit loop() 
10 loops, best of 3: 34.4 ms per loop 

mi var th için iyi bir açıklama ese sonuçları ve aynı görevi yerine getirmek için daha hızlı bir yol var mı?

+2

'noloop()'() döngü 'den (~% 15) daha hızlı olma' bakılmaksızın ... –

+0

Ben de üzerinde ters olsun hem python2 ve python3. –

+1

OP önerdiğinden (makinemde% 28) daha hızlı "loop" alıyorum. Python 3.4.1 | Anaconda 2.1.0, IPython 2.2.0 – Roberto

cevap

0

Sonuçlarınızı yeniden üretemedim, ancak numpy.multiply kullanarak önemli bir hızlanma (2 kat) elde edebileceğimi buldum. out argümanını kullanarak, belleğin zaten ayrılmış olması ve tmp'un out'a kopyalanmasını ortadan kaldırabilirsiniz. Benim makinede

def out_loop(): 
    out = np.empty((arr1.size, arr2.size)) 
    for i in range(arr1.size): 
     np.multiply(arr1[i], arr2, out=out[i].reshape((1, arr2.size))) 
     out[i] *= 2 
    return out 

Sonuçlar: Elde

In [32]: %timeit out_loop() 
100 loops, best of 3: 17.7 ms per loop 

In [33]: %timeit loop() 
10 loops, best of 3: 28.3 ms per loop 
İlgili konular