python中的Numpy二維數組遍歷與二維數組切片後遍歷效率比較

python-numpy使用中,可以用雙層 for循環對數組元素進行訪問,也可以切片成每一行後進行一維數組的遍歷。

代碼如下:

import numpy as np
import time
NUM = 160


a=np.random.random((NUM,NUM))
start = time.time()
for i in range(NUM):
    for j in range(NUM):
        if a[i][j] == 1.0:
            pass
end1 =  time.time()

for ii in range(NUM):
    b = a[ii,:]
    for jj in range(NUM):
        if b[jj] == 1.0:
            pass 
end2 =  time.time()
print("end1",end1-start)
print("end2",end2-end1)

由於生成的是[0,1)中的數,因此兩種操作會遍歷所有的元素。多輪測試後,耗時如下:

當NUM為160時:

end1 0.006983518600463867
end2 0.003988742828369141

當NUM為1600時:

end1 0.71415114402771
end2 0.45178747177124023

結論:切片後遍歷更快
原因:
樓主還暫不明確

一個想法:

b=a[ii,:]

在numpy中,為瞭提高效率,這種切片出來的子矩陣其實都是原矩陣的引用而已,所以改變子矩陣,原矩陣還是會變的
所以在內層循環中,第二種方法是在那一行元素所在的內存進行尋找。而第一種方法是先定位到行,再定位到列,所以比較慢?
大傢是怎麼想的呢?

關於numba在小數據量下的速度慢於普通操作

什麼是numba?

numba

實驗比較:

import numpy as np
import time
NUM = 160
from numba import jit
a=np.random.random((NUM,NUM))

@jit(nopython=True)
def fun1(a):
    for i in range(NUM):
        for j in range(NUM):
            if a[i][j] == 1.0:
                pass

def fun2(a):
    for i in range(NUM):
        for j in range(NUM):
            if a[i][j] == 1.0:
                pass
    
@jit(nopython=True)
def fun3(a):
    for ii in range(NUM):
        b = a[ii,:]
        for jj in range(NUM):
            if b[jj] == 1.0:
                pass 


def fun4(a):
    for iii in range(NUM):
        b = a[iii,:]
        for jjj in range(NUM):
            if b[jjj] == 1.0:
                pass 

start = time.time()
fun1(a)
end1 =  time.time()
fun2(a)
end2 =  time.time()
fun3(a)
end3 =  time.time()
fun4(a)
end4 =  time.time()
print("end1",end1-start)
print("end2",end2-end1)
print("end3",end3-end2)
print("end4",end4-end3)

首先,當NUM為1600時,結果如下:

end1 0.2991981506347656 #無切片,有加速
end2 0.6372940540313721 #無切片,無加速
end3 0.08377814292907715 #有切片,有加速
end4 0.358079195022583   #有切片,無加速

其他條件相同的情況下,有切片的速度更快。同樣,有numba加速的也比沒加速的快。
但當NUM =160時,結果如下:

end1 0.29620814323425293   #無切片,有加速
end2 0.006980180740356445  #無切片,無加速
end3 0.08580684661865234   #有切片,有加速
end4 0.0029993057250976562 #有切片,無加速

有切片依舊比無切片的快。但是有numba加速的卻比沒有numba加速的慢。
原來@jit(nopython=True)隻是對函數進行修飾,第一次調用會進行編譯,編譯成機器碼,之後速度就會很快。

實驗代碼如下:

import numpy as np
import time
NUM = 160
from numba import jit
a=np.random.random((NUM,NUM))

@jit(nopython=True)
def fun1(a):
    for i in range(NUM):
        for j in range(NUM):
            if a[i][j] == 1.0:
                pass

def fun2(a):
    for i in range(NUM):
        for j in range(NUM):
            if a[i][j] == 1.0:
                pass
    
@jit(nopython=True)
def fun3(a):
    for ii in range(NUM):
        b = a[ii,:]
        for jj in range(NUM):
            if b[jj] == 1.0:
                pass 


def fun4(a):
    for iii in range(NUM):
        b = a[iii,:]
        for jjj in range(NUM):
            if b[jjj] == 1.0:
                pass 

for b in range(4):
    start = time.time()
    fun1(a)
    end1 =  time.time()
    fun2(a)
    end2 =  time.time()
    fun3(a)
    end3 =  time.time()
    fun4(a)
    end4 =  time.time()
    print("end1",end1-start)
    print("end2",end2-end1)
    print("end3",end3-end2)
    print("end4",end4-end3)
    print("---")

結果如下:

end1 0.29421305656433105
end2 0.0059833526611328125
end3 0.08181905746459961
end4 0.0029909610748291016

end1 0.0
end2 0.005949735641479492
end3 0.0
end4 0.004008769989013672

end1 0.0
end2 0.006977558135986328
end3 0.0
end4 0.00399017333984375

end1 0.0
end2 0.005974292755126953
end3 0.0
end4 0.003837108612060547

結論:

numba加速時,第一次需要編譯,需要耗時。之後調用就不需要瞭。

到此這篇關於python中的Numpy二維數組遍歷與二維數組切片後遍歷效率比較的文章就介紹到這瞭,更多相關Numpy二維數組遍歷與二維數組切片後遍歷效率比較內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: