2010-06-11 11 views
11

Bir piton dict yaklaşık 10.000.000 ürün ile dolduruyorum. Dict (veya hashtables) anlayışım, çok fazla elementin içine girdiğinde, yeniden boyutlandırma ihtiyacının, oldukça zamana mal olan bir operasyon olduğudur.Bir python dict bir başlangıç ​​kapasitesi vermek mümkün mü (ve yararlıdır)

Bir python deyiminde, en az n öğeyi depolayacağınızı ve böylece belleği baştan ayırabileceğinizi söylemenin bir yolu var mı? Ya da bu optimizasyon benim koşu hızım için iyi olmaz mı?

(Ve hayır, benim küçük senaryonun yavaşlığından şüphe duymadım, şimdi bunu nasıl yapamayacağımı şimdi yapamam. Bu, Java'da yapacağım bir şey, başlangıçtaki the hashset sağ)

+1

olası kopyası [Python - Başlangıç ​​kapasitesine sahip bir liste oluşturun] (http://stackoverflow.com/questions/311775/python-create-a-list-with-initial-capacity) – msw

+7

kopya parçası. Bir dict bir liste ile aynı değildir. –

+0

olası bir kopyası [Python'da bir sözlük için başlangıç ​​boyutu nasıl ayarlanır?] (Http://stackoverflow.com/questions/1298636/how-to-set-initial-size-for-a-dictionary-in-python) – psmears

cevap

18

İlk olarak, bir sözlük boyutunu başlangıçta ayarlayabileceğinizi söylediğinizi duydum, ancak bunun nasıl yapılacağını anlatan hiçbir belge veya PEP görmedim.

Bunu aklımda tutarak, aşağıda açıklanan ürün miktarınızda bir analiz yaptım. Her seferinde sözlüğümü yeniden boyutlandırmak biraz zaman alabilir, ancak en azından performansını test edene kadar endişelenmeden ilerlemenizi tavsiye ederim.

Yeniden boyutlandırmayı belirlemede bizi ilgilendiren iki kural, öğe sayısı ve yeniden boyutlandırma faktörüdür. Bir sözlük, 2/3 işaretinin üzerine koyarak öğenin eklenmesiyle 2/3 dolduğunda kendini yeniden boyutlandıracaktır. 50.000 elemanın altında 4 kat artacaktır, bu miktarın üzerinde 2 kat olacaktır. 10.000.000 öğenin tahminini kullanarak (2^23 ve 2^24 arasında) sözlüğünüz 15 kez yeniden boyutlandırılacaktır (50k'nin 7 katı altında, Yukarıda 8 kez). Başka bir yeniden boyutlandırma, 11.100.000'den sonra gerçekleşir.

Güncel öğeleri yeniden boyutlandırma ve değiştirme, biraz zaman alacaktır, ancak merak ediyorum ki, yakınlarda bulunan kodda neler olup bittiğini farkedin. Her bir sınır boyunca beş yerde eklemeleri 2^3 ile 2^24 arasındaki sözlük boyutlarından karşılaştıran bir zamanlama paketini bir araya getirdim ve "kenarlık" eklemeleri "sınırsız" ekleme işlemlerinden ortalama 0.4 nanosaniye daha uzundu. Bu% 0.17 daha uzun ... muhtemelen kabul edilebilir. Tüm işlemler için minimum 0,2085 mikrosaniyeydi ve maksimum 0.2412 mikrosaniyeydi.

Bu durum çok iyi anlaşılırdır ve kodunuzun performansını kontrol ederseniz, lütfen bir düzenleme ile takip edin! Sözlük iç için My birincil kaynak PyCon 2010'da Brandon Rodos tarafından verilen görkemli bir konuşmaydı: The Mighty Dictionary

+0

Mighty Dictionary'e bağlantı artık ölü (link rot) –

+0

Link tekrar çalışıyor. – Celeo

2

Evet burada can ve ben de sizinkine ilgilidir başka bir kişinin söz bulunan bir çözümdür:

d = {} 
for i in xrange(4000000): 
d[i] = None 
# 722ms 

d = dict(itertools.izip(xrange(4000000), itertools.repeat(None))) 
# 634ms 

dict.fromkeys(xrange(4000000)) 
# 558ms 

s = set(xrange(4000000)) 
dict.fromkeys(s) 
# Not including set construction 353ms 

Bunlar, belirli bir boyuttaki bir sözlüğü başlatmanın farklı yollarıdır.

+11

Başkasının [cevap] (http://stackoverflow.com/a/1298905/12892) kullanıyorsanız, [onu] (http://stackoverflow.com/users/107366/ants-aasma) kredisini verin, özellikle cevaplar [cc by-sa 3.0] altında lisanslandığında (http://creativecommons.org/licenses/by-sa/3.0/) [attribution required] (http://blog.stackoverflow.com/2009/06) /)/ilişkilendirme gerekli. Heck, kendini ölçüt olarak yeniden üretebilirdin. –

İlgili konular