2008-10-22 13 views
35

Ich lief etwas dynamischer Programmcode (versuchte Brute-Force widerlegen die Collatz-Vermutung = P) und ich benutzte ein Diktat, um die Längen der Ketten zu speichern, die ich bereits berechnet hatte. Offensichtlich hatte es irgendwann keinen Speicher mehr. Gibt es eine einfache Möglichkeit, eine Variante von dict zu verwenden, die Teile von sich selbst auf die Festplatte auslagern wird, wenn es keinen Platz mehr hat? Offensichtlich wird es langsamer als ein In-Memory-Diktat, und es wird wahrscheinlich am Ende meinen Festplattenplatz verschlingen, aber das könnte auf andere Probleme, die nicht so sinnlos sind, zutreffen.Python Disk-Based Dictionary

Ich erkannte, dass ein Disk-basiertes Wörterbuch ist so ziemlich eine Datenbank, so dass ich manuell eine mit sqlite3 implementiert, aber ich habe es nicht auf intelligente Weise und hatte es jedes Element in der DB eins nach a Zeit ... es war ungefähr 300x langsamer.

Ist der schlaueste Weg, um meine eigenen Sätze von dicts zu erstellen, nur eine im Speicher zu halten, und sie auf eine effiziente Weise auslagern?

Antwort

20

Hash-on-Disk ist in der Regel mit Berkeley DB oder etwas ähnliches adressiert - mehrere Optionen sind in der Python Data Persistence documentation aufgeführt. Sie können es mit einem In-Memory-Cache versehen, aber ich würde zuerst mit der nativen Leistung testen; mit Betriebssystem-Caching an Ort und Stelle könnte es etwa gleich herauskommen.

6

Das letzte Mal, als ich mit einem solchen Problem konfrontiert wurde, schrieb ich SQLite statt eines Diktats und hatte eine massive Leistungssteigerung. Diese Leistungssteigerung war zumindest teilweise auf die Indexierungsmöglichkeiten der Datenbank zurückzuführen. abhängig von Ihren Algorithmen, YMMV.

Ein Thin Wrapper, der SQLite Abfragen in __getitem__ und __setitem__ tut, ist nicht viel Code zu schreiben.

+0

Wie genau würden Sie die Indexierung von sqlite verwenden? So wie ich es hier gemacht habe, habe ich eine Tabelle wie folgt erstellt: "cur.execute ('create table vals (intx INTEGER, chainlen INTEGER)')", dann I "cur.execute ('SELECT * von vals where indx =% d '% i) "für eine Suche. – Claudiu

+2

Tabelle Vals (Indix INTEGER PRIMARY KEY, Ketten INTEGER) –

+0

@Claudiu - mein Programm war so, dass ich einige Logik in der Datenbank-Ebene implementieren konnte, so könnte ich die DB tun, filtern und so; es war mehr als nur ein dummer Laden. –

0

Sie sollten mehr als ein Element nach dem anderen mitbringen, wenn es eine Heuristik gibt, die die wahrscheinlichsten Elemente sind, die als nächstes abgerufen werden sollen, und vergessen Sie nicht die Indizes, die Charles erwähnt.

2

Mit ein bisschen Nachdenken scheint es, als könnten Sie die shelve module zu tun, was Sie wollen.

6

Das shelve Modul kann es tun; jedenfalls sollte es einfach zu testen sein. Statt:

self.lengths = {} 

tun:

import shelve 
self.lengths = shelve.open('lengths.shelf') 

Der einzige Haken ist, dass die Schlüssel zu den Regalen Strings sein müssen, so dass Sie

self.lengths[indx] 

mit

ersetzen müssen werde
self.lengths[str(indx)] 

(Ich nehme an, Ihre Schlüssel sind nur ich ntegers, nach Ihrem Kommentar zu Charles Duffy Post)

Es gibt keine integrierte Caching im Speicher, aber Ihr Betriebssystem kann das für Sie sowieso tun.

[eigentlich, das ist nicht ganz richtig: Sie können das Argument 'Writeback = True' bei der Erstellung übergeben. Damit soll sichergestellt werden, dass Listen und andere veränderbare Dinge im Regal korrekt funktionieren. Aber ein Nebeneffekt ist, dass das gesamte Wörterbuch im Speicher zwischengespeichert wird.Da dies Probleme für Sie verursacht, ist es wahrscheinlich keine gute Idee :-)]

+1

Ich habe dies tatsächlich versucht, aber es war viel zu langsam .. ich denke, ich brauche eine Art manueller Paging-Lösung, um irgendeine angemessene Geschwindigkeit zu erhalten. – Claudiu

52

Die 3rd Party shove Modul ist auch einen Blick wert. Es ist dem shelve sehr ähnlich, da es ein einfaches dict-ähnliches Objekt ist, jedoch kann es auf verschiedene Backends (wie Datei, SVN und S3) gespeichert werden, bietet optionale Komprimierung und ist sogar threadsicher. Es ist ein sehr praktisches Modul

from shove import Shove 

mem_store = Shove() 
file_store = Shove('file://mystore') 

file_store['key'] = value 
+2

Dies verdient mehr Aufmerksamkeit als es wird. Es kann auch mit SQLite verwendet werden, wenn Sie keinen separaten Server oder Berkeley DB verwenden möchten, wenn Sie SQLite nicht verwenden möchten. –

+0

Ja, ich habe lange nach dieser Art von Modul gesucht. Planen Sie, Redis-Unterstützung seit dem, was wir für kv speichern verwenden. – k4ml

0

Ich versuche es noch nicht, aber Hamster DB ist vielversprechend und eine Python-Schnittstelle verfügt.

2

ich gelesen habe Sie shelve denken, ist zu langsam, und Sie versucht, Ihre eigenen dict mit SQLite zu hacken.

tat andere dies auch:

http://sebsauvage.net/python/snyppets/index.html#dbdict

es ziemlich effizient scheint (und sebsauvage ist ein ziemlich guter Coder). Vielleicht könntest du es versuchen?

Verwandte Themen