web-dev-qa-db-ja.com

python:dequeとリストのパフォーマンス比較

In python docs dequeは、左側または右側から項目をポップ/追加するために高度に最適化された特別なコレクションであることがわかります。たとえば、ドキュメントによると:

両端キューは、スタックとキューの一般化です(名前は「デッキ」と発音され、「ダブルエンドキュー」の略です)。 Dequeは、スレッドセーフでメモリ効率の良い追加とポップをサポートし、どちらの方向でもほぼ同じO(1)パフォーマンスと同じです。

リストオブジェクトは同様の操作をサポートしますが、高速の固定長操作と、両方を変更するpop(0)およびinsert(0、v)操作のメモリ移動コストO(n))に最適化されています基になるデータ表現のサイズと位置。

ipythonを使用して比較することにしました。誰かが私がここで間違ったことを説明できますか?

In [31]: %timeit range(1, 10000).pop(0)
 10000 loops, best of 3: 114 us per loop

In [32]: %timeit deque(xrange(1, 10000)).pop() 
10000 loops, best of 3: 181 us per loop

In [33]: %timeit deque(range(1, 10000)).pop()
1000 loops, best of 3: 243 us per loop
33
Oleg Tarasenko

Could anyone explain me what I did wrong here

はい、タイミングはリストまたは両端キューを作成する時間に支配されます。 popを実行する時間は、比較して重要ではありません。

代わりに、テストしようとしているもの(ポップ速度)をセットアップ時間から分離する必要があります。

In [1]: from collections import deque

In [2]: s = range(1000)

In [3]: d = deque(s)

In [4]: s_append, s_pop = s.append, s.pop

In [5]: d_append, d_pop = d.append, d.pop

In [6]: %timeit s_pop(); s_append(None)
10000000 loops, best of 3: 115 ns per loop

In [7]: %timeit d_pop(); d_append(None)
10000000 loops, best of 3: 70.5 ns per loop

そうは言っても、パフォーマンスに関するdequeとlistの本当の違いは次のとおりです。

  • DequesはO(1) appendleft()およびpopleft()の速度ですが、リストにはO(n) insert(0、value)およびpop(0)のパフォーマンス。

  • リスト追加パフォーマンスは、内部でrealloc()を使用するため、ヒットとミスになります。その結果、単純なコードでは楽観的なタイミングが過大になる傾向があり(reallocはデータを移動する必要がないため)、実際のコードではタイミングが非常に遅くなります(断片化によりすべてのデータが強制的に再割り当てされるため)。対照的に、deque appendのパフォーマンスは、データの再割り当てや移動を行わないため一貫しています。

70

価値があるもの:

> python -mtimeit -s 'import collections' -s 'c = collections.deque(xrange(1, 100000000))' 'c.pop()'
10000000 loops, best of 3: 0.11 usec per loop

> python -mtimeit -s 'c = range(1, 100000000)' 'c.pop()'
10000000 loops, best of 3: 0.174 usec per loop

> python -mtimeit -s 'import collections' -s 'c = collections.deque()' 'c.appendleft(1)'
10000000 loops, best of 3: 0.116 usec per loop

> python -mtimeit -s 'c = []' 'c.insert(0, 1)'
100000 loops, best of 3: 36.4 usec per loop

ご覧のとおり、本当に輝くのはappendleftinsertです。

20
sberry