我注意到通過「直接」迭代通過numpy數組迭代通過tolist
方法迭代之間有意義的區別。見下面定時:什麼是迭代通過一個numpy數組最快的方法
直接
[i for i in np.arange(10000000)]
經由tolist
[i for i in np.arange(10000000).tolist()]
考慮到我發現了一種更快的方法。我想問問還有什麼可以讓它變得更快?
什麼是最快的方式來遍歷一個numpy數組?
我注意到通過「直接」迭代通過numpy數組迭代通過tolist
方法迭代之間有意義的區別。見下面定時:什麼是迭代通過一個numpy數組最快的方法
直接
[i for i in np.arange(10000000)]
經由tolist
[i for i in np.arange(10000000).tolist()]
考慮到我發現了一種更快的方法。我想問問還有什麼可以讓它變得更快?
什麼是最快的方式來遍歷一個numpy數組?
這些都是我的機器慢
In [1034]: timeit [i for i in np.arange(10000000)]
1 loop, best of 3: 2.16 s per loop
上計時,如果我直接生成的範圍(PY3所以這是一個genertor)倍要好得多。以此爲基礎來理解這個尺寸的列表。
In [1035]: timeit [i for i in range(10000000)]
1 loop, best of 3: 1.26 s per loop
tolist
首先將arange轉換爲列表;需要更長的時間,但迭代仍然是一個列表
In [1036]: timeit [i for i in np.arange(10000000).tolist()]
1 loop, best of 3: 1.6 s per loop
使用list()
上 - 同時在陣列上直接迭代;這表明直接迭代首先執行此操作。
In [1037]: timeit [i for i in list(np.arange(10000000))]
1 loop, best of 3: 2.18 s per loop
In [1038]: timeit np.arange(10000000).tolist()
1 loop, best of 3: 927 ms per loop
同一時間在.tolist
In [1039]: timeit list(np.arange(10000000))
1 loop, best of 3: 1.55 s per loop
一般來說,如果你必須循環迭代一個,名單上的工作速度更快。訪問列表中的元素更簡單。
查看索引返回的元素。
a[0]
是另一個numpy
對象;它由a
中的值構成,但不是簡單的取值
list(a)[0]
是同一類型;該列表只是[a[0], a[1], a[2]]]
In [1043]: a = np.arange(3)
In [1044]: type(a[0])
Out[1044]: numpy.int32
In [1045]: ll=list(a)
In [1046]: type(ll[0])
Out[1046]: numpy.int32
但tolist
陣列成純列表轉換,在這種情況下,作爲整數的列表。它比list()
做更多的工作,但它在編譯代碼。
In [1047]: ll=a.tolist()
In [1048]: type(ll[0])
Out[1048]: int
一般不要使用list(anarray)
。它很少做任何有用的事情,並且不如tolist()
那樣強大。
迭代數組的最快方式是什麼 - 無。至少不在Python中;在c代碼中有快速的方法。
a.tolist()
是從數組創建列表整數的最快矢量化方法。它迭代,但在編譯代碼中這樣做。
但是你真正的目標是什麼?
感謝@hpaulj這非常接近實際回答我的問題,因爲你陳述了......「什麼是迭代數組的最快方法 - 無。」我可能會選擇這個作爲我的答案,但我會稍微打開它。 – piRSquared
這實際上並不奇怪。讓我們從最慢的一個時間開始研究這些方法。
[i for i in np.arange(10000000)]
此方法要求蟒伸入numpy的陣列(存儲在C存儲器範圍),一個元件的時間,在存儲器分配Python對象,並創建一個指針列表中的該對象。每次你在存儲在C後端的numpy數組之間進行管道操作並將其拉入純python時,會產生間接費用。這種方法增加了10,000,000次的成本。
下一頁:
[i for i in np.arange(10000000).tolist()]
在這種情況下,使用.tolist()
使得單個調用numpy的Ç後端和分配所有一次性的元素添加到列表中。然後您使用python遍歷該列表。
最後:
list(np.arange(10000000))
這基本上做同樣的事情如上,但它創造numpy的原生類型對象(例如np.int64
)的列表。使用list(np.arange(10000000))
和np.arange(10000000).tolist()
應該差不多同時。
所以,在迭代而言,使用numpy
的主要優點是你不需要進行迭代。操作以向量化的方式應用於陣列。迭代只會減慢速度。如果你發現自己迭代數組元素,你應該尋找一種方法來重構你正在嘗試的算法,這種方式只使用numpy操作(它有很多內建的!),或者如果真的有必要,你可以使用np.apply_along_axis
,np.apply_over_axis
或np.vectorize
。
但是'list(np.arange(10))'和'np.arange(10).tolist()'之間存在細微的差別:第一個會導致一個「np.int64」列表的第二個Python的int列表。第一個問題可能會導致序列化等問題。使用json。 json會在第一個錯誤,因爲它不能處理'np.int64' – MaxNoe
你是絕對正確的。 – James
這是非常有用的,這就是爲什麼我投了贊成票,我希望別人也這麼做。我現在要解決這個問題了,因爲我仍然希望看到通過數組進行迭代的其他選項。 – piRSquared
*是*奇數。我自己嘗試了好幾次,似乎將它轉換爲列表確實使其始終更快。感謝您將此帶入光明中。 –
只需迭代並獲取列表或做一些處理呢?使用'list(np.arange(1000000))'看起來非常快。 – Divakar
@Divakar參見http://stackoverflow.com/a/40575522/2336654 – piRSquared