これらの結果はすべて、CPython 3.5.2で得られています。セット操作の奇妙なパフォーマンス
set
クラスの一部の操作で奇妙なパフォーマンスが発生したことに気付きました。
整数だけを含む2つのセットの和集合を実行するのに必要な時間を測定しました。今回は、セットのサイズにもよります。意外にも、これは整数の「密度」にも依存します。
X軸は(それぞれの経験のため、互いからランダムかつ独立に選択された)二組のサイズの合計である:ここでのプロットです。 y軸は秒単位(ログスケール)です。
濃度がd
であることは、合計がN/d
の整数からN
の整数をサンプリングすることによってセットがインスタンス化されたことを意味します。言い換えれば、密度が0.5の場合、ある間隔の整数の半分を取る一方、密度が0.1の場合、ある(より大きい)間隔の整数の1/10を取る。
いくつかの結果を得るための最小限のコードです(必要に応じて、私がプロットに使用した完全なコードを投稿できますが、それは長くなります)。
import time
import random
import numpy
def get_values(size, density):
return set(random.sample(range(int(size/density)), size))
def perform_op(size, density):
values1 = get_values(size, density)
values2 = get_values(size, density)
t = time.time()
result = values1 | values2
return time.time()-t
size = 10000000
for density in [0.05, 0.1, 0.5, 0.99]:
times = [perform_op(size, density) for _ in range(10)]
print('density: %.2f, mean time: %.4f, standard deviation: %.4f' % (density, numpy.mean(times), numpy.std(times)))
ユニオン:
density: 0.05, time: 0.9846, standard deviation: 0.0440
density: 0.10, time: 1.0141, standard deviation: 0.0204
density: 0.50, time: 0.5477, standard deviation: 0.0059
density: 0.99, time: 0.3440, standard deviation: 0.0020
セット同じサイズを有する、略最速と最も遅いとの間の計算時間の要因3があります。 また、低密度ではさらにばらつきがあります。
面白いことに(perform_op
機能にvalues1 & values2
でvalues1 | values2
を置き換える)交差点のために、我々はまた、非一定のパフォーマンスを持っていますが、パターンが異なっている、ということである:
density: 0.05, time: 0.3928, standard deviation: 0.0046
density: 0.10, time: 0.4876, standard deviation: 0.0041
density: 0.50, time: 0.5975, standard deviation: 0.0127
density: 0.99, time: 0.3806, standard deviation: 0.0015
私は他のセットの操作をテストしていません。
なぜこのような違いがあるのかわかりません。私が知っていることから、Pythonのセットはハッシュテーブルで実装されているので、ハッシュがよく広がっている限り、整数の密度は重要ではありません。
これらの異なるパフォーマンスの原因は何ですか?
ハッシュセットの効率は、同じバケットにハッシュする要素の数によって異なります。これは、セット自体のサイズと数値の分布に依存します。私は誰かに 'set'の実装にもっと慣れさせて、適切な答えを提供させます。 –