Seite 1 von 1
Dumb von sehr umfangreicher Liste/Dict (18mio Einträgen)
Verfasst: Samstag 20. November 2010, 07:53
von Auctor
Hallo zusammen,
ich hätte da eine Frage bzw. ein Problem bei dem Ihr mir vielleicht weiterhelfen könntet.
Ich generiere ein Dict mit sehr vielen Einträgen (ca 18mio, sys.getsizeof gibt mir für dieses Dict eine Größe von 805306648 bytes (768mb) an). Da dieses Dict dann auch nur wieder als Eingabe für ein Script dient (und es knapp 11 std. dauert diese Daten zu generieren) möchte ich dieses nun "dumpen".
Mein erster Ansatz war das ganze zu pickeln (mit cPickle und protocol 2).
Leider läuft dies schon ewig und scheint zu keinem Ergebnis zu führen (i7 mit 12 GB Ram). Der pickle Vorgang läuft nun schon über 24 std und das bisher Erstellte pickle File ist knapp 200 mb groß.
Das gleiche Ergebnis bekomme ich wenn ich das ganze als Liste erstelle bzw. direkt meinen Graphen (das is eigentlich das Ergebnis welches ich auf der Platte haben möchte. Der Graph ist allerdings dann auch wieder ein Dict. Dieser Graph soll dann als Eingabe für ein anderes Script dienen. D.h. ich muss das ganze auch wieder in den Speicher laden können mit pickle oder über shelve). Pickle scheint ein Problem mit den vielen Einträgen zu haben.
Mein zweiter Ansatz war das ganze mit shelve zu lösen. Das Ergebnis bisher ist leider das selbe. Er rattert und rattert, der Speicher läuft voll und es wird zwar ein File auf der Platte erstellt aber seeeeeeeeeehr langsam (ab einer bestimmten Größe 200kb pro stunde).
Ich weis nicht ob es etwas bringt wenn ich den Code poste. Anbei für das dict und shelve
Code: Alles auswählen
f = open('dict.cpickle','wb')
cPickle.dump(dict,f,protocol=2)
f.close()
Code: Alles auswählen
db = shelve.open('dict.db')
for key in dict:
db[key] = dict[key]
db.close()
Wie geschrieben glaube ich dass pickle bzw. shelve ein Problem mit den Unglaublich vielen Einträgen haben und nicht mal unbedingt die Filegröße dass Problem ist.
Hat vielleicht jemand einen Tipp für mich bzw. Erfahrung mit ähnlichen Problemen.
Vielen Dank schon mal für eure Hilfe
Martin
Re: Dumb von sehr umfangreicher Liste/Dict (18mio Einträgen)
Verfasst: Samstag 20. November 2010, 08:25
von numerix
Da du keine Angaben über die Daten(typen) in deinem dict machst, ist es vielleicht ein unbrauchbarer Vorschlag:
Spricht etwas dagegen, den Inhalt des dict in ein schlichtes Textfile zu schreiben?
Re: Dumb von sehr umfangreicher Liste/Dict (18mio Einträgen)
Verfasst: Samstag 20. November 2010, 08:45
von Auctor
Hallo numerix,
nun ja eigentlich nicht da hast du recht. Ich habe das auch schon versucht (als txt im dot graph format). Das Problem ist dann eher das laden des ganzen. Ich möchte nur einmal diesen Monster Graphen erstellen (benutze networkx. Graph hat ca 50k knoten und 18mio kanten, jeweils mit mehreren labeln) und dann meinen Algorithmus darauf laufen lassen (sehr oft mit unterschiedlichen Kombinationen). Der Graph ist bei networkx auch als Dict im Dict gespeichert und Schlussendlich möchte ich genau diesen als File haben und Ihn dann in mein Script laden.
Vielleicht verstehe ich das ganze jetzt auch falsch. Ein schneller google hat die eval() funktion ausgespuckt. Die kannte ich noch nicht (bin sehr neu bei python.) Vielleicht geht es genau damit. Vielen dank schon mal. Das probiere ich gleich aus.
EDIT: da ich defaultdicts in dicts (mit listen) benutze und networkx ebenso verschachtelte dicts glaube ich dass das mit dem textfile nicht klappt. Mist.
Gruß
Martin
Re: Dumb von sehr umfangreicher Liste/Dict (18mio Einträgen)
Verfasst: Samstag 20. November 2010, 09:23
von numerix
Auctor hat geschrieben:Ein schneller google hat die eval() funktion ausgespuckt. Vielleicht geht es genau damit.
Das würde mich sehr wundern, denn eval() ist alles andere als performant.
Re: Dumb von sehr umfangreicher Liste/Dict (18mio Einträgen)
Verfasst: Samstag 20. November 2010, 09:34
von ntrunk
Hi,
wie wär's mit einer Datenbank? Das ist doch eigentlich das Mittel der Wahl bei großen Datenmengen.
Gruß
Norbert
Re: Dumb von sehr umfangreicher Liste/Dict (18mio Einträgen)
Verfasst: Samstag 20. November 2010, 09:57
von numerix
numerix hat geschrieben:Das würde mich sehr wundern, denn eval() ist alles andere als performant.
Habe es eben mal ausprobiert. Auf meinem Rechner (der ist zwar nicht ganz so üppig ausgestattet wie deiner, aber auch recht flott) schafft er es mit eval() überhaupt nicht - nach einer Weile des Wartens kommt nur die lapidare Auskunft "killed" und dann war's das.
Ein paar weitere Überlegungen:
Wenn du die Knoten von 1 bis 5e4 durchnummerierst (und, falls du mehr Informationen zu einem Knoten brauchst, in einem Extra-dict nur die Knoten den Nummern zuordnest), dann kannst du deinen Graphen als Liste von Listen beschreiben. Bei 18e6 Kanten wären das 360 Kanten pro Knoten im Schnitt. Das in einem Textfile zu sichern dauert auf meinem Rechner ca. 5 s. Das Einlesen ca. 20 s. Die Zusatzinformationen zu jedem Knoten ergibt ggf. nochmal ein File mit 5e4 Zeilen - also auch allenfalls eine Sache von Sekunden.
Edit: Vergessen: Mit pickle ist das deutlich langsamer, aber dennoch nur eine Sache von wenigen Minuten.
Edit Edit: Gilt für Python 3.1 anscheinend nicht ... s.u.
Re: Dumb von sehr umfangreicher Liste/Dict (18mio Einträgen)
Verfasst: Samstag 20. November 2010, 10:15
von BlackJack
@numerix: Da Du schon Testcode geschrieben hast: Wie sieht's denn mit JSON vs. Pickle aus?
Re: Dumb von sehr umfangreicher Liste/Dict (18mio Einträgen)
Verfasst: Samstag 20. November 2010, 10:22
von Auctor
hallo nochmal und schon mal tausend dank für die vielen Antworten.
@numerix: ja das hört sich nach ner sehr guten Idee an! ich teste das gleich mal! vielen dank!
Gruß
Martin
Re: Dumb von sehr umfangreicher Liste/Dict (18mio Einträgen)
Verfasst: Samstag 20. November 2010, 10:52
von numerix
BlackJack hat geschrieben:@numerix: Da Du schon Testcode geschrieben hast: Wie sieht's denn mit JSON vs. Pickle aus?
Für 5000(!) Knoten mit je 360 Kanten:
Python 2.6 (64 Bit)
Code: Alles auswählen
json
Write ... 6.19309782982
Read ... 30.0668818951
pickle
Write ... 4.99308109283
Read ... 11.2194750309
text
Write ... 0.429654836655
Read ... 1.78832387924
marshal
Write ... 0.158332109451
Read ... 0.38414311409
Python 3.1 (64 Bit)
Code: Alles auswählen
json
Write ... 3.87854194641
Read ... 6.16133904457
pickle
Write ... 0.128656148911
Read ... 0.848262071609
text
Write ... 0.729530096054
Read ... 3.05102205276
marshal
Write ... 0.0895040035248
Read ... 0.224417924881
Re: Dumb von sehr umfangreicher Liste/Dict (18mio Einträgen)
Verfasst: Samstag 20. November 2010, 20:16
von noisefloor
Hallo,
schon alleine die Datenmenge in Kombination mit der Datenstruktur (Schlüssel+Wert) schreit förmlich nach einem Key-Value Store. Das sollte auch deutlich performanter sein als Pickel & Co.
Gruß, noisefloor
Re: Dumb von sehr umfangreicher Liste/Dict (18mio Einträgen)
Verfasst: Samstag 20. November 2010, 22:59
von Defnull
Mich wundert, das noch niemand marshal vorgeschlagen hat. Man kann es selten zu etwas gebrauchen, aber gerade hier macht es Sinn.
Re: Dumb von sehr umfangreicher Liste/Dict (18mio Einträgen)
Verfasst: Samstag 20. November 2010, 23:02
von DasIch
Es gibt uebrigens Graphdatenbanken die dafuer da sind... ueberraschung Graphen zu speichern z.B. neo4js.
Re: Dumb von sehr umfangreicher Liste/Dict (18mio Einträgen)
Verfasst: Samstag 20. November 2010, 23:17
von numerix
Defnull hat geschrieben:Mich wundert, das noch niemand marshal vorgeschlagen hat. Man kann es selten zu etwas gebrauchen, aber gerade hier macht es Sinn.
Guter Hinweis. Habe die Laufzeiten oben ergänzt.
Re: Dumb von sehr umfangreicher Liste/Dict (18mio Einträgen)
Verfasst: Montag 22. November 2010, 11:12
von mkesper
Ist pickle beidesmal cpickle bzw. beidesmal nicht? Dann hätte sich ja einiges an der Performance getan...
Re: Dumb von sehr umfangreicher Liste/Dict (18mio Einträgen)
Verfasst: Montag 22. November 2010, 17:01
von cofi
`pickle` benutzt in Python3 die C-Implementierung, wenn verfügbar, in Python2 nicht.
Re: Dumb von sehr umfangreicher Liste/Dict (18mio Einträgen)
Verfasst: Dienstag 23. November 2010, 20:06
von anogayales
Gibt es keine Cjson Implementierung? Ist ja echt grauenhaft was die json Implementierung da abliefert.
Re: Dumb von sehr umfangreicher Liste/Dict (18mio Einträgen)
Verfasst: Dienstag 23. November 2010, 20:11
von DasIch
Die Implementierung ist zumindest teilweise durchauch in C und an die anderen kann es Format bedingt ohnehin schon nicht dran kommen.
Desweiteren ist die pickle Implementation auch nichts was irgendjemand ansonsten ernsthaft nutzen wuerde. pickle.load bzw. pickle.loads kann zig unterschiedliche Exceptions werfen wenn die Eingabe invalid ist die nicht dokumentiert sind.
Re: Dumb von sehr umfangreicher Liste/Dict (18mio Einträgen)
Verfasst: Mittwoch 24. November 2010, 15:43
von lunar
@DasIch: In Python 2.6 ist "json" ausschließlich in Python implementiert.
Ob tatsächlich niemand die pickle-Implementierung (sic!) ernsthaft einsetzen würde, darüber lässt sich trefflich streiten. Es gibt meines Erachtens genügend Situationen, in denen pickle sinnvoll ist.