ティムピーターズはこれが遅い理由を答えましたが、それを改善する方法を見てみましょう。
あなたの例にこだわるsum(range(...))
(ここのメモリに収まるように、あなたの例よりも係数10小さい):
import numpy
import array
L = list(range(10**7))
A = array.array('l', L)
N = numpy.array(L)
%timeit sum(L)
10 loops, best of 3: 101 ms per loop
%timeit sum(A)
1 loop, best of 3: 237 ms per loop
%timeit sum(N)
1 loop, best of 3: 743 ms per loop
この方法でも、numpyはボックス化/ボックス化解除する必要があり、追加のオーバーヘッドがあります。速くするには、numpy cコード内に留まる必要があります:
%timeit N.sum()
100 loops, best of 3: 6.27 ms per loop
したがって、リストソリューションから派手なバージョンまで、これは実行時に16倍になります。
これらのデータ構造の作成にかかる時間も確認してみましょう
%timeit list(range(10**7))
1 loop, best of 3: 283 ms per loop
%timeit array.array('l', range(10**7))
1 loop, best of 3: 884 ms per loop
%timeit numpy.array(range(10**7))
1 loop, best of 3: 1.49 s per loop
%timeit numpy.arange(10**7)
10 loops, best of 3: 21.7 ms per loop
明確な勝者:Numpy
また、データ構造の作成には、合計と同じかそれ以上の時間がかかります。メモリの割り当てが遅い。
それらのメモリ使用量:
sys.getsizeof(L)
90000112
sys.getsizeof(A)
81940352
sys.getsizeof(N)
80000096
したがって、これらは数値ごとに8バイトかかり、オーバーヘッドが異なります。32ビット整数を使用する範囲では十分なので、一部のメモリを安全にすることができます。
N=numpy.arange(10**7, dtype=numpy.int32)
sys.getsizeof(N)
40000096
%timeit N.sum()
100 loops, best of 3: 8.35 ms per loop
しかし、私のマシンでは、64ビット整数を追加する方が32ビット整数よりも高速であるため、メモリ/帯域幅に制限がある場合にのみ価値があります。