Dumb von sehr umfangreicher Liste/Dict (18mio Einträgen)

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Auctor
User
Beiträge: 12
Registriert: Mittwoch 24. Februar 2010, 18:56

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
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

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?
Auctor
User
Beiträge: 12
Registriert: Mittwoch 24. Februar 2010, 18:56

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
Zuletzt geändert von Auctor am Samstag 20. November 2010, 09:32, insgesamt 1-mal geändert.
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

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.
ntrunk
User
Beiträge: 83
Registriert: Sonntag 7. September 2008, 23:09
Wohnort: Buchen (Odenwald)

Hi,

wie wär's mit einer Datenbank? Das ist doch eigentlich das Mittel der Wahl bei großen Datenmengen.

Gruß
Norbert
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

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.
Zuletzt geändert von numerix am Samstag 20. November 2010, 10:53, insgesamt 1-mal geändert.
BlackJack

@numerix: Da Du schon Testcode geschrieben hast: Wie sieht's denn mit JSON vs. Pickle aus?
Auctor
User
Beiträge: 12
Registriert: Mittwoch 24. Februar 2010, 18:56

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
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

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
Zuletzt geändert von numerix am Samstag 20. November 2010, 23:16, insgesamt 1-mal geändert.
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

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
Benutzeravatar
Defnull
User
Beiträge: 778
Registriert: Donnerstag 18. Juni 2009, 22:09
Wohnort: Göttingen
Kontaktdaten:

Mich wundert, das noch niemand marshal vorgeschlagen hat. Man kann es selten zu etwas gebrauchen, aber gerade hier macht es Sinn.
Bottle: Micro Web Framework + Development Blog
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Es gibt uebrigens Graphdatenbanken die dafuer da sind... ueberraschung Graphen zu speichern z.B. neo4js.
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

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.
Benutzeravatar
mkesper
User
Beiträge: 919
Registriert: Montag 20. November 2006, 15:48
Wohnort: formerly known as mkallas
Kontaktdaten:

Ist pickle beidesmal cpickle bzw. beidesmal nicht? Dann hätte sich ja einiges an der Performance getan...
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

`pickle` benutzt in Python3 die C-Implementierung, wenn verfügbar, in Python2 nicht.
http://docs.python.org/py3k/library/pickle.html hat geschrieben:The pickle module has an transparent optimizer (_pickle) written in C. It is used whenever available. Otherwise the pure Python implementation is used.
anogayales
User
Beiträge: 456
Registriert: Mittwoch 15. April 2009, 14:11

Gibt es keine Cjson Implementierung? Ist ja echt grauenhaft was die json Implementierung da abliefert.
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

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.
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.
Antworten