2012-01-11 44 views
1

我需要函數聚合器,它將兩個列表減少爲一個總數。 '物品'應該是布爾人的矢量。Python;實現按元素向量乘法的最高性能方法

所以,我寫這些功能:

def element_wise_multiplication(weights, items): 
    return map(lambda x, y: x * y, weights, items) 

def total(weights, items): 
    return sum(element_wise_multiplication(weights, items)) 

他們看起來OK我,但問題是,探查表明,隨着它拉姆達行負責運行的95%,所以它的性能幾乎不可接受。

什麼是最有效的實現方法?

P.S.我知道NumPy的數組,但我想在這個上使用PyPy。或者在這種情況下使用它不值得嗎?

+1

在PyPy上,只需要在簡單的循環中編寫它就會好得多。再加上你的代碼會更具可讀性。 – fijal 2012-01-12 12:14:47

回答

3

可以照顧與發電機像這樣:

from itertools import izip 
value = sum((x * y) for x, y in izip(weights, items)) 

izip完成同樣的事情內置zip,但是沒有內存高架。

+1

當然,內存開銷更高,但是... value = sum([(x * y)for x,y in izip(權重,項目)])'實際上更快:) – 2012-01-11 22:51:36

+0

這給了24%的優化。有什麼機會進一步推動它? – Zotov 2012-01-11 22:53:10

+0

@RicardoCárdenes謝謝!優化47%。這還差不多) – Zotov 2012-01-11 23:01:50

1

嘗試只是這樣的:

def total(weights, items): 
    return sum (x * y for x, y in zip(weights, items)) 
2

雖然你提到不希望在這種情況下使用numpy,但可能值得關注速度差異。

最好的非numpy解決方案似乎是一個使用izip的發電機,這個發電機勉強超過了zip。

In [31]: %timeit sum(x*y for x,y in zip(weights,items)) 
    10000 loops, best of 3: 158 us per loop 

    In [32]: %timeit sum(x*y for x,y in izip(weights,items)) 
    10000 loops, best of 3: 125 us per loop 

但是當我們使用numpy的陣列,我們得到:

In [33]: %timeit (np_weights,np_items).sum() 
    100000 loops, best of 3: 9.08 us per loop 

的numpy的解決方案是快了整整14倍。如果這真的是你的代碼中的瓶頸,那麼numpy就是要走的路。