2016-06-03 11 views
3

Ich bin ein Neuling in Lua (benutze es für das Torch7-Framework). Ich habe eine Eingabe-Feature-Datei, die etwa 1,4 GB groß ist (Textdatei). Die einfache io.open-Funktion gibt beim Versuch, diese Datei zu öffnen, den Fehler 'nicht genug Speicher' aus. Beim Durchblättern der Benutzergruppen und der Dokumentation sehe ich, dass seine möglicherweise eine Lua-Einschränkung ist. Gibt es einen Workaround dafür? Oder mache ich etwas falsch beim Lesen der Datei?Wie lese ich große Dateien (> 1GB) in lua?

EDIT: Die Eingabedatei, die ich versuche zu lesen, enthält Bildfunktionen, auf die ich mein Modell trainieren möchte. Diese Datei ist geordnet ({start-tag} ... Inhalt ... {end-tag} {start-tag} ... und so weiter ...), also ist es in Ordnung, wenn ich diese laden kann Abschnitte (Start-Tag bis End-Tag) nacheinander. Ich möchte jedoch, dass alle diese Abschnitte in den Speicher geladen werden.

+1

Sind Sie sicher, dass das 'nicht genügend Speicher' erscheint nach dem 'io.open'? Das scheint nicht richtig zu sein. Ist es jedoch möglich, dass Sie die Datei in Blöcken lesen? Benötigen Sie _really_ brauchen die Loch-Datei im Speicher Beachten Sie, dass das '*' in 'file: read (" * all ")' in lua 5.3 obsolet ist (ich weiß nicht, welche Version Fackel verwendet) – pschulz

+1

Torch verwendet LuaJIT, die hat Speicherbeschränkungen. Siehe z.B. http://stackoverflow.com/questions/35155444/why-is-luajits-memory-limited-to-1-2-gb-on-64-bit-platforms. – moteus

+0

@pschulz: Der nicht genügend Speicherfehler erscheint, während 'local content = file: read (" * all ")' ausgeführt wird. – NightFury13

Antwort

2

Es stellt sich heraus, dass das Problem beim Laden großer Dateien am einfachsten ist, wenn Sie den Brenner auf Lua5.2 oder höher aufrüsten! Wie von den Entwicklern von Torch auf der Fackel7-Google-Gruppe vorgeschlagen.

cd ~/torch 
./clean.sh 
TORCH_LUA_VERSION=LUA52 ./install.sh 

Die Speichergrenzen existieren ab der Version 5.2 nicht mehr! Ich habe das getestet und es funktioniert gut!

Referenz: https://groups.google.com/forum/#!topic/torch7/fi8a0RTPvDo


Eine andere mögliche Lösung (die elegantere und ist ähnlich zu dem, was @ Adam in seiner Antwort vorgeschlagen) ist die Datei Zeile für Zeile und Verwendung Tensoren zu verwenden, lesen oder tds die speichern Daten, da dies Speicher außerhalb von Luajit verwendet. Ein Codebeispiel ist wie folgt, dank Vislab.

Daten von diesem Tensor zu lesen ist einfach und schnell. Zum Beispiel, wenn Sie die 10'th Zeile in der Datei lesen wanto (die in der 10'th Position auf dem Tensor sein werden), können Sie einfach wie folgt vor:

local line_string = ffi.string(file_tensor[10]:data()) -- this will convert into a string var 

Ein Wort der Warnung: Diese belegt mehr Speicherplatz im Speicher und ist möglicherweise nicht optimal für einige Fälle, in denen einige Zeilen viel länger sind als die anderen. Aber wenn Sie keine Speicherprobleme haben, kann dies sogar ignoriert werden, denn beim Laden von Tensoren aus Dateien in den Speicher ist es blitzschnell und kann dabei einige graue Haare speichern.

Referenz: https://groups.google.com/forum/#!topic/torch7/fi8a0RTPvDo

0

Ich hatte noch nie die Notwendigkeit, eine Datei so groß zu lesen, aber wenn Sie nicht genügend Speicher haben, müssen Sie wahrscheinlich Zeile für Zeile lesen. Nach einiger schnellen Recherche fand ich dies aus der lua Website:

buff = buff..line.."\n" 

Buff ist eine neue Zeichenfolge mit 50.020 Bytes, und der alten Zeichenfolge in jetzt> Müll. Nach zwei Schleifenzyklen ist Buff eine Zeichenfolge mit 50.040 Bytes, und es gibt zwei alte Zeichenfolgen, die insgesamt mehr als 100 KByte Müll enthalten. Daher entscheidet Lua ganz richtig, dass es eine gute Zeit ist, seinen Müllsammler zu starten, und so befreit er diese 100 Kbytes. Das Problem ist, dass dies alle zwei Zyklen passieren wird, und so wird Lua seinen Müllsammler zweitausend Mal ausführen, bevor die Schleife beendet wird. Selbst bei all dieser Arbeit wird der Speicherverbrauch ungefähr dreimal so groß wie die Dateigröße sein. Um die Sache noch schlimmer zu machen, muss jede Verkettung den gesamten String-Inhalt (50 KByte und wachsend) in die neue Zeichenkette kopieren.

So scheint es, dass das Laden von großen Dateien wahnsinnigen Mengen an Speicher verwendet, auch wenn Sie es Zeile für Zeile gelesen haben und eine Verkettung jedes Mal wie folgt verwenden:

local buff = "" 
while 1 do 
    local line = read() 
    if line == nil then break end 
    buff = buff..line.."\n" 
end 

Sie dann vorschlagen ein Speichererhalt Prozess:

function newBuffer() 
     return {n=0}  -- 'n' counts number of elements in the stack 
    end 

    function addString (stack, s) 
    table.insert(stack, s)  -- push 's' into the top of the stack 
    for i=stack.n-1, 1, -1 do 
     if string.len(stack[i]) > string.len(stack[i+1]) then break end 
     stack[i] = stack[i]..table.remove(stack) 
    end 
    end 

    function toString (stack) 
    for i=stack.n-1, 1, -1 do 
     stack[i] = stack[i]..table.remove(stack) 
    end 
    return stack[1] 
    end 

Das nimmt viel weniger Speicher als zuvor. Alle Informationen stammen von: http://www.lua.org/notes/ltn009.html
Hoffe, dass geholfen hat.

+2

Vorsicht: alter Code. Es gibt kein "Tint" oder "Tremove" usw. Aber die Idee funktioniert immer noch. – pschulz

+0

Sortieren von. Die speicherfreundlichste Möglichkeit, eine vollständige Datei in den Speicher zu lesen, ist immer noch 'file: read (" * a ")'. Das Lesen kleinerer Abschnitte ist nur sinnvoll, wenn Sie die vorherigen Abschnitte vom GC erfassen lassen können. – siffiejoe

+0

@siffiejoe: also ist das Lesen der Datei mit 'file: read (" * a ")' die beste Option? Kann man in Lua einfach keine großen Dateien lesen? :/ – NightFury13