2017-06-10 4 views
3

私は5,000,000の整数リストを持っています。そして、私はリストを数が少ない配列にすることを望んでいます。私は次のコードを試しました:numpy.array(リスト)が遅い

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

このパフォーマンスの向上により、35fpsのビデオを処理できるようになりました。最も重要なことに、C++で数千行のコードを書き直す必要はありません。 – Yinan

+0

私のMacでは約5倍の速さですが。 – Yinan

+0

@Yinanまた、 'numpyをnpとし、' numpyをnpとしてインポートするだけでなく、 'np.uint8_t [:] arr = np.zeros(len(inp)、dtype = np.uint8) ')。操作は基本的に帯域幅が制限されているため、できるだけ小さいdtypeを選択することでこれを大幅に高速化できます。私はウィンドウを使用しているので、 'int32'はMacではおそらく' int64'なので、なぜあなたのものが第2因子より遅く見えるのか説明できます。あなたの「数字」は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 'ret'がすでに割り当てられていて、適切な形でコピーが再配置されていないと言うのは、これが速い理由です。 –

+0

@SeverinPappadeux、OPは前回の試行について話しています。ループ –

0

小さな整数の大きなリストを作成します。 numpy松葉杖を使用:指定DTYPE

In [623]: arr8 = np.array(alist, 'uint8') 
In [624]: timeit arr8 = np.array(alist, 'uint8') 
1 loop, best of 3: 508 ms per loop 

の配列を作成します

In [622]: timeit [i for i in alist] 
10 loops, best of 3: 193 ms per loop 

を(何もしない)プレーンなリストの反復の

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 

と時間を私たちはして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 

よく配列で作業するよりも高速であることが知られていますかなりの「スタートアップ」オーバーヘッドがあることを示しています。

関連する問題