2017-06-10 167 views
3

所以我有一個含有5,000,000個整數的列表。我想將這個列表覆蓋到一個數組中。我試過下面的代碼:numpy.array(list)slow

numpy.array(list) 

但它很慢。

我對此操作進行了100次基準測試,並在列表中循環了100次。沒有太大的區別。

任何好主意如何讓它更快?

+0

你肯定你的名單隻包含整數嗎?結果數組的dtype是什麼? – chrisb

+0

是的,我對此非常肯定。這是一個平面圖像數據陣列。所以輸入和輸出數組都是uint8型 – Yinan

+0

@ user3201090我對我的答案做了更新,previus並不快,這個是 –

回答

1

如果你有你可以創建一個函數,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倍以上。

+0

由於這種性能改進,我現在可以用35 fps處理視頻,最重要的是,不必在C++中重寫數千行代碼。 – Yinan

+0

雖然在我的Mac上只有5倍左右的速度。 – Yinan

+0

@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

1

我覺得這是快,我查了時間:

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 --- 
+0

爲什麼會在整個列表中循環更快? – Yinan

+0

@ user3201090我會說在copyto中沒有重新分配,因爲'ret'已經被分配並且形狀正確,這就是爲什麼它很快 –

+0

@SeverinPappadeux,OP在談論我以前的嘗試,循環 –

0

列出一個小整數列表;使用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 

這是衆所周知的是使用數組是比快名單,但是有一個重大的「啓動」開銷。