如果這個問題有點太基本,請原諒。
我在學習NumPy時,通過NumPy陣列為什么這么快?了解到NumPy陣列之所以快,是因為有兩件事
np.com.cn
np.array()是由相同的dtype組成的,因此得到了參考的區域性的好處。
通過像uFunc這樣的東西,可以進行矢量操作。
因此,有理由認為計算速度應該是:
(uFuncs)
(uFuncs with np arrays)> (loops with np arrays)> (loops with list).
然而,下面的代碼顯示,速度實際上是,
(uFuncs with np arrays)>(loops with list)>(loops with np arrays)。換句話說,盡管使用np陣列的uFUncs是最快的,但使用串列的回圈比使用np陣列的回圈快。誰能解釋一下為什么會這樣?
預先感謝您的回答!
import numpy as np
np.random.seed(0)
arr=np.arange(1,1000)
arrlist=[]
for i in range(1,1000):
arrlist.append(i)
#case0: list loop: arrlist.append(i)
def list_loop(values)。#values: 我想取倒數的一維陣列。
output=[]
for i in range(len(values))。
output.append(1.0/values[i])
return output
#case1: np陣列回圈 def nparray_loop(values)。#values: 我想取倒數的一維陣列。
output=np.empty(len(values))
for i in range(len(value))。
output[i]=1.0/values[i]
return output
#case2: uFunc
def nparray_uFunc(values)。
return 1.0/values
print("list loop computation time:")
%timeit list_loop(arrlist)
print('
')
print("np陣列回圈計算時間:")
%timeit nparray_loop(arr)
print('
')
print("uFunc計算時間:")
%timeit nparray_uFunc(arr)
輸出:
list回圈計算時間。
185 μs ± 5.63 μs per loop (mean ± std. dev. of 7 runs, 10000loops each)
np陣列回圈的計算時間。
4.28 ms ± 402 μs per loop (mean ± std. dev. of 7 runs, 100 loop each)
uFunc的計算時間。
5.42 μs ± 1.23 μs per loop (mean ± std. dev. of 7 runs, 100000 loop each)
uj5u.com熱心網友回復:
一個串列在內部表示為一個Python物件的向量。 numpy陣列是一個復雜的資料結構,其中實際的數字資料是以原始機器格式存盤的。
要在一個 Python 串列上呼叫一個 Python 函式,Python 只是從串列中摘取適當的元素并呼叫該函式。 要在一個 numpy 陣列上呼叫一個 Python 函式,Python 必須從 numpy 陣列的每個原始元素中取出,并將其轉換為適當的 Python 表示法,然后呼叫 Python 函式。
Numpy對于矢量操作來說是非常快的。 如果你打算一個元素一個元素地看資料,那么它的效率就會降低。
uj5u.com熱心網友回復:
你對資料定位的思考是正確的,但這并不是全部的情況。
Python 串列或帶有 dtype = object 的 NumPy 陣列持有 references;每個元素都指向一個外部資料物件。然而,NumPy 陣列也可以有數字 dtypes;每個元素直接存盤資料。
與數字 dtypes 不同,一個參考不會告訴你它所指向的物件的型別。在像 [1, 0.5, 2] 這樣的 Python 串列的回圈中,你需要檢查 values[i] 的型別,并為 每一次 迭代選擇適當的 / (float-int 或 float-float 除法)。在NumPy陣列上使用矢量代碼1.0/values,其數字型別為np.array([1, 0, 2]),你檢查陣列的數字型別numpy.int64并在迭代前只需找到合適的/一次。這節省了大量的時間,因為迭代的次數增加了。
現在,為什么NumPy陣列上的數字dtype的回圈會比同等的矢量化代碼慢?一些語言在編譯程序中進行了型別推理,所以他們可以知道values是一個NumPy陣列,并且values[i]在每個迭代中都必須是一個numpy.int64值。然而,Python 沒有做型別推理,而是選擇在每次迭代時檢查 values[i] 的型別,完全沒有意識到它每次都會得到相同的答案 numpy.int64。為了解決Python回圈中缺乏型別推理的問題,NumPy的矢量代碼允許Python使用C回圈(這并不是說你可以為了同樣的速度而切換到C,NumPy是高度優化的)。
現在,為什么 NumPy 陣列上的回圈比 Python 串列上的回圈要慢呢?這是因為 NumPy 陣列上的 values[i] 創建了一個新的 numpy.int64 標量物件,而 Python list 上的 values[i] 只是使用一個已經存在的物件。每次迭代創建和丟棄一個物件都需要時間,當所有這些被丟棄的物件觸發垃圾回收時,可能需要更多的時間。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/326886.html
標籤:
上一篇:Mysql查詢限制運行緩慢
