2013-05-16 24 views
7

我把我的神經網絡從純粹的python改爲numpy,但現在它工作得更慢。所以,我想這兩個功能:爲什麼numpy比python慢​​?如何使代碼更好地執行

def d(): 
    a = [1,2,3,4,5] 
    b = [10,20,30,40,50] 
    c = [i*j for i,j in zip(a,b)] 
    return c 

def e(): 
    a = np.array([1,2,3,4,5]) 
    b = np.array([10,20,30,40,50]) 
    c = a*b 
    return c 

timeit d = 1.77135205057

timeit E = 17.2464673758

numpy的是10倍慢。爲什麼是這樣以及如何正確使用numpy?

+0

也許相關:http://stackoverflow.com/questions/5956783/numpy-float-10x-slower-than-builtin-in-arithmetic-operations –

+1

你應該使用更大的數組進行這種測試 –

回答

14

我會認爲這種差異是因爲你在e中構建列表和數組,而你只在d中構造列表。試想一下:

import numpy as np 

def d(): 
    a = [1,2,3,4,5] 
    b = [10,20,30,40,50] 
    c = [i*j for i,j in zip(a,b)] 
    return c 

def e(): 
    a = np.array([1,2,3,4,5]) 
    b = np.array([10,20,30,40,50]) 
    c = a*b 
    return c 

#Warning: Functions with mutable default arguments are below. 
# This code is only for testing and would be bad practice in production! 
def f(a=[1,2,3,4,5],b=[10,20,30,40,50]): 
    c = [i*j for i,j in zip(a,b)] 
    return c 

def g(a=np.array([1,2,3,4,5]),b=np.array([10,20,30,40,50])): 
    c = a*b 
    return c 


import timeit 
print timeit.timeit('d()','from __main__ import d') 
print timeit.timeit('e()','from __main__ import e') 
print timeit.timeit('f()','from __main__ import f') 
print timeit.timeit('g()','from __main__ import g') 

這裏的功能fg避免重新創建每次繞列表/陣列,我們得到了非常相似的性能:

1.53083586693 
15.8963699341 
1.33564996719 
1.69556999207 

注意list-COMP + zip仍然獲勝。但是,如果我們的陣列足夠大,numpy的勝手了:

t1 = [1,2,3,4,5] * 100 
t2 = [10,20,30,40,50] * 100 
t3 = np.array(t1) 
t4 = np.array(t2) 
print timeit.timeit('f(t1,t2)','from __main__ import f,t1,t2',number=10000) 
print timeit.timeit('g(t3,t4)','from __main__ import g,t3,t4',number=10000) 

我的結果是:

0.602419137955 
0.0263929367065 
3
import time , numpy 
def d(): 
    a = range(100000) 
    b =range(0,1000000,10) 
    c = [i*j for i,j in zip(a,b)] 
    return c 

def e(): 
    a = numpy.array(range(100000)) 
    b =numpy.array(range(0,1000000,10)) 
    c = a*b 
    return c 



#python ['0.04s', '0.04s', '0.04s'] 
#numpy ['0.02s', '0.02s', '0.02s'] 

嘗試用更大的陣列......即使與創建的開銷陣列numpy的快得多

2

numpy的數據結構是對加入較慢/構建

這裏一些測試:

from timeit import Timer 
setup1 = '''import numpy as np 
a = np.array([])''' 
stmnt1 = 'np.append(a, 1)' 
t1 = Timer(stmnt1, setup1) 

setup2 = 'l = list()' 
stmnt2 = 'l.append(1)' 
t2 = Timer(stmnt2, setup2) 

print('appending to empty list:') 
print(t1.repeat(number=1000)) 
print(t2.repeat(number=1000)) 

setup1 = '''import numpy as np 
a = np.array(range(999999))''' 
stmnt1 = 'np.append(a, 1)' 
t1 = Timer(stmnt1, setup1) 

setup2 = 'l = [x for x in xrange(999999)]' 
stmnt2 = 'l.append(1)' 
t2 = Timer(stmnt2, setup2) 

print('appending to large list:') 
print(t1.repeat(number=1000)) 
print(t2.repeat(number=1000)) 

結果:

appending to empty list: 
[0.008171333983972538, 0.0076482562944814175, 0.007862921943675175] 
[0.00015624398517267296, 0.0001191077336243837, 0.000118654852507942] 
appending to large list: 
[2.8521017080411304, 2.8518707386717446, 2.8022625940577477] 
[0.0001643958452675065, 0.00017888804099541744, 0.00016711313196715594] 
-1

我不認爲numpy的是緩慢的,因爲它必須考慮到編寫和調試所需的時間。程序越長,發現問題或添加新功能(程序員時間)就越困難。 因此,使用更高級別的語言可以在相同的智能時間和技能下創建程序複合體並可能更高效。

無論如何,一些有趣的工具來優化是:

- Psyco的是JIT(準時,「實時」),它在運行時的代碼優化。並行化是加速程序執行的一種好方法,只要這種方式可以充分分離即可。

- 編織是內NumPy的一個模塊進行通信Python和其功能C.一個是閃擊,這需要一個線的Python,所述透明平移C,並且每個呼叫被執行優化的版本的時間。在進行第一次轉換時需要大約一秒鐘的時間,但更高的速度通常可以獲得以上所有。它不是Numexpr或Psyco字節碼,或者接口C是NumPy,但是你自己的函數直接用C語言編寫並完全編譯和優化。