2013-12-17 31 views
10

numpy diziler toplanmasıyla. hızla ı numpy diziler listesinin öğeye göre toplamını yapmak istediğimizi varsayalım öğeye göre

timeit.timeit('sum(array(tosum), axis=0)', 
       setup='from numpy import sum; from __main__ import tosum, array', 
       number=10000) 
75.02289700508118 
timeit.timeit('sum(tosum, axis=0)', 
       setup='from numpy import sum; from __main__ import tosum', 
       number=10000) 
78.99106407165527 

azaltın

(büyüklük yaklaşık iki siparişlerin ayarlamak için) daha hızlıdır:

timeit.timeit('reduce(add,tosum)', 
       setup='from numpy import add; from __main__ import tosum', 
       number=10000) 
1.131795883178711 

Hatta azaltmak gibi görünüyor üzerinde anlamlı bir kurşun sahiptir numpy.sum korkunç gibi görünüyor olmayan numpy toplamı (1E6 içindir bu yukarıdaki kez çalışır ziyade 1E4 unutmayın):

timeit.timeit('reduce(add,tosum)', 
       setup='from numpy import add; from __main__ import tosum', 
       number=1000000) 
109.98814797401428 

timeit.timeit('sum(tosum)', 
       setup='from __main__ import tosum', 
       number=1000000) 
125.52461504936218 

orada denemelisiniz diğer yöntemler musunuz? Sıralamayı açıklayan var mı? Liste ilk önce bir numpy diziye açıksa


Düzenleme

numpy.sum kesinlikle daha hızlıdır: Ancak

tosum2 = array(tosum) 
timeit.timeit('sum(tosum2, axis=0)', 
       setup='from numpy import sum; from __main__ import tosum2', 
       number=10000) 
1.1545608043670654 

, bir defasında bir miktar yapıyor ilgileniyorum sadece Bu yüzden diziyi numpy dizisine dönüştürmek hala gerçek bir performans cezasına çarptırılır.

+2

Bu np.sum'un ilk önce oluşturduğunu ve dizileceğini ve daha sonra performansının düşük olduğunu açıklayacak şekilde özetlediğini tahmin ediyorum ... Bir np'yi geçmiş olsaydınız en hızlı olacağını tahmin ediyorum. ndarray ile başlayacak. – mgilson

+1

Ve 'sum' içinde gizli olan' 0 + tosum [0] 'atladığından beri, toplamın 1/11'e düşmesini beklerim. – mgilson

+0

Bu mantıklı. Bir dizi ayrı diziyle başlıyorum, bu yüzden onları bir numpy dizisine dönüştürmek, ilk olarak benim için yaptıklarının aynı performans cezasına çarpacaktır (çünkü sadece bir kere toplam yapıyorum). – lnmaurer

cevap

4

Aşağıdakiler reduce ile rekabet halindedir ve tosum listesinin yeterince uzun olması durumunda daha hızlıdır. Ancak, çok daha hızlı değil ve daha fazla kod. (reduce(add, tosum) emin güzel.) Orijinal tosum için

def loop_inplace_sum(arrlist): 
    # assumes len(arrlist) > 0 
    sum = arrlist[0].copy() 
    for a in arrlist[1:]: 
     sum += a 
    return sum 

Zamanlama. reduce(add, tosum) hızlıdır:

In [128]: tosum = [rand(100,100) for n in range(10)] 

In [129]: %timeit reduce(add, tosum) 
10000 loops, best of 3: 73.5 µs per loop 

In [130]: %timeit loop_inplace_sum(tosum) 
10000 loops, best of 3: 78 µs per loop 

Zamanlama dizisinin çok daha uzun liste için. Şimdi loop_inplace_sum daha hızlı.

In [131]: tosum = [rand(100,100) for n in range(500)] 

In [132]: %timeit reduce(add, tosum) 
100 loops, best of 3: 5.09 ms per loop 

In [133]: %timeit loop_inplace_sum(tosum) 
100 loops, best of 3: 4.4 ms per loop 
+0

İlginç. Hızın nereden geldiği hakkında düşünceleriniz var mı? Belki azaltmaktan daha az yükü var? (Ben sadece ~ 10 büyük dizi birlikte ekleyerek, bu yüzden muhtemelen azaltmak ile sopa, ama bu yöntem geleceği bilmek güzeldir.) – lnmaurer

+0

Evet, daha az havai: yerinde ek, bazı nesne oluşturma ortadan kaldırır. Eğer 'sum + = a' ifadesini 'sum = sum + a' ile değiştirirseniz, 'küçült' seçeneğinden biraz daha yavaş olur. –

İlgili konular