所以我有一個含有5,000,000個整數的列表。我想將這個列表覆蓋到一個數組中。我試過下面的代碼:numpy.array(list)slow
numpy.array(list)
但它很慢。
我對此操作進行了100次基準測試,並在列表中循環了100次。沒有太大的區別。
任何好主意如何讓它更快?
所以我有一個含有5,000,000個整數的列表。我想將這個列表覆蓋到一個數組中。我試過下面的代碼:numpy.array(list)slow
numpy.array(list)
但它很慢。
我對此操作進行了100次基準測試,並在列表中循環了100次。沒有太大的區別。
任何好主意如何讓它更快?
如果你有cython你可以創建一個函數,definetly更快。但只是一個警告:如果列表中存在無效元素(非整數或太大整數),將會崩潰。
我在這裏使用IPython魔術(%load_ext cython
和%%cython
),重點是展示函數的外觀 - 不是說明如何編譯Cython代碼(這不難,Cythons「如何編譯」文檔是相當不錯的)。
%load_ext cython
%%cython
cimport cython
import numpy as np
@cython.boundscheck(False)
cpdef to_array(list inp):
cdef long[:] arr = np.zeros(len(inp), dtype=long)
cdef Py_ssize_t idx
for idx in range(len(inp)):
arr[idx] = inp[idx]
return np.asarray(arr)
而且時機:
import numpy as np
def other(your_list): # the approach from @Damian Lattenero in the other answer
ret = np.zeros(shape=(len(your_list)), dtype=int)
np.copyto(ret, your_list)
return ret
inp = list(range(1000000))
%timeit np.array(inp)
# 315 ms ± 5.42 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit np.array(inp, dtype=int)
# 311 ms ± 2.28 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit other(inp)
# 316 ms ± 3.97 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit to_array(inp)
# 23.4 ms ± 1.15 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
所以它的速度更快的10倍以上。
由於這種性能改進,我現在可以用35 fps處理視頻,最重要的是,不必在C++中重寫數千行代碼。 – Yinan
雖然在我的Mac上只有5倍左右的速度。 – Yinan
@Yinan您還可以使用'cdef np.uint8_t [:] arr = np.zeros(len(inp),dtype = np.uint8)''(要求'cimport numpy as np'以及import numpy as np ')。該操作基本上是帶寬限制的,所以選擇最小的dtype可能會顯着提高速度。我在Windows上使用windows'int32'可能是'int64',所以它可以解釋爲什麼你的速度慢了2倍。你的「數字」是兩倍長。 – MSeifert
我覺得這是快,我查了時間:
import numpy as np
import time
start_time = time.time()
number = 1
elements = 10000000
your_list = [number] * elements
ret = np.zeros(shape=(len(your_list)))
np.copyto(ret, your_list)
print("--- %s seconds ---" % (time.time() - start_time))
--- 0.7615997791290283 seconds ---
爲什麼會在整個列表中循環更快? – Yinan
@ user3201090我會說在copyto中沒有重新分配,因爲'ret'已經被分配並且形狀正確,這就是爲什麼它很快 –
@SeverinPappadeux,OP在談論我以前的嘗試,循環 –
列出一個小整數列表;使用numpy
柺杖:
In [619]: arr = np.random.randint(0,256, 5000000)
In [620]: alist = arr.tolist()
In [621]: timeit alist = arr.tolist() # just for reference
10 loops, best of 3: 108 ms per loop
而且時間爲普通列表迭代(沒有做任何事情)
In [622]: timeit [i for i in alist]
10 loops, best of 3: 193 ms per loop
讓指定的D型
In [623]: arr8 = np.array(alist, 'uint8')
In [624]: timeit arr8 = np.array(alist, 'uint8')
1 loop, best of 3: 508 ms per loop
數組我們可以得到2倍的改進與fromiter
;顯然它沒有檢查。即使列表是數字和字符串的混合,np.array
也可以工作。它也處理列表等列表
In [625]: timeit arr81 = np.fromiter(alist, 'uint8')
1 loop, best of 3: 249 ms per loop
,當我們在整個事情做數學處理數組的優點是顯而易見的:
In [628]: timeit arr8.sum()
100 loops, best of 3: 6.93 ms per loop
In [629]: timeit sum(alist)
10 loops, best of 3: 74.4 ms per loop
In [630]: timeit 2*arr8
100 loops, best of 3: 6.89 ms per loop
In [631]: timeit [2*i for i in alist]
1 loop, best of 3: 465 ms per loop
這是衆所周知的是使用數組是比快名單,但是有一個重大的「啓動」開銷。
你肯定你的名單隻包含整數嗎?結果數組的dtype是什麼? – chrisb
是的,我對此非常肯定。這是一個平面圖像數據陣列。所以輸入和輸出數組都是uint8型 – Yinan
@ user3201090我對我的答案做了更新,previus並不快,這個是 –