Frage

Ich verwende Python-Multiprocessing, um eine temporäre Ausgabedatei pro Prozess zu generieren. Sie können mehrere GB groß sein und ich mache mehrere zehn davon. Diese temporären Dateien müssen verknüpft werden, um die gewünschte Ausgabe zu erhalten. Dies ist der Schritt, der sich als Engpass (und Parallelitätskiller) herausstellt. Gibt es ein Linux-Tool, das die verknüpfte Datei erstellt, indem es die Metadaten des Dateisystems ändert und den Inhalt nicht tatsächlich kopiert? Solange es auf einem Linux-System funktioniert, wäre das für mich akzeptabel. Eine dateisystemspezifische Lösung ist jedoch keine große Hilfe.

Ich bin nicht OS- oder CS-geschult, aber theoretisch sollte es möglich sein, einen neuen Inode zu erstellen und über die Inode-Zeigerstruktur aus dem Inode der Dateien zu kopieren, aus denen ich kopieren möchte, und diese Inodes dann zu trennen. Gibt es ein Dienstprogramm, das dies erledigt? Angesichts der Fülle gut durchdachter Unix-Dienstprogramme habe ich das voll und ganz erwartet, konnte aber nichts finden. Daher meine Frage zu SO. Das Dateisystem befindet sich auf einem Blockgerät, einer Festplatte, falls diese Informationen von Bedeutung sind. Ich habe nicht das Vertrauen, dies selbst zu schreiben, da ich noch nie zuvor auf Systemebene programmiert habe. Daher sind Zeiger (auf C / Python-Code-Snipppets) sehr hilfreich.

War es hilfreich?

Lösung

Selbst wenn es ein solches Tool gäbe, könnte dies nur funktionieren, wenn die Dateien außer den letzten Es wurde garantiert, dass die Größe ein Vielfaches des Blocks des Dateisystems beträgt Größe.

Wenn Sie steuern, wie die Daten in die temporären Dateien geschrieben werden, und Sie wissen Wie groß jeder sein wird, können Sie stattdessen wie folgt tun:

  1. Erstellen Sie vor dem Starten der Mehrfachverarbeitung die endgültige Ausgabedatei und wachsen Sie es auf die endgültige Größe von fseek() ing bis zum Ende wird dies eine erstellen Datei mit geringer Dichte .

  2. Starten Sie die Mehrfachverarbeitung und übergeben Sie jedem Prozess den FD und den Offset bestimmte Scheibe der Datei.

    Auf diese Weise füllen die Prozesse gemeinsam die einzelne Ausgabedatei. Entfernen der Notwendigkeit, sie später zusammen zu katzen.

    EDIT

    Wenn Sie die Größe der einzelnen Dateien nicht vorhersagen können, aber der Verbraucher der Die endgültige Datei kann mit sequentieller Eingabe (im Gegensatz zu wahlfreiem Zugriff) arbeiten Geben Sie dem Verbraucher cat tmpfile1 .. tmpfileN, entweder auf stdin

    cat tmpfile1 ... tmpfileN | consumer
    

    oder über Named Pipes (mit Bashs Process Substitution):

    consumer <(cat tmpfile1 ... tmpfileN)
    

Andere Tipps

Sie geben an, dass Sie die Größe jeder temporären Datei nicht im Voraus kennen. Vor diesem Hintergrund ist es meiner Meinung nach am besten, ein FUSE -Dateisystem zu schreiben, das die Chunks als Single darstellt große Datei, während sie als einzelne Dateien im zugrunde liegenden Dateisystem gespeichert werden.

In dieser Lösung bleiben Ihre produzierenden und konsumierenden Apps unverändert. Die Produzenten schreiben eine Reihe von Dateien aus, die die FUSE-Ebene als als einzelne Datei erscheinen lässt. Diese virtuelle Datei wird dann dem Verbraucher präsentiert.

FUSE verfügt über Bindungen für eine Reihe von Sprachen, einschließlich Python . Wenn Sie sich einige Beispiele hier oder hier (dies sind für verschiedene Bindungen), dies erfordert überraschend wenig Code.

Ich glaube nicht, Inode ist möglicherweise ausgerichtet, daher ist es möglicherweise nur möglich, wenn Sie in Ordnung sind, einige Nullen (oder unbekannte Bytes) zwischen der Fußzeile einer Datei und dem Header einer anderen Datei zu lassen.

Anstatt diese Dateien zu verketten, möchte ich vorschlagen, das Analysetool neu zu gestalten, um die Beschaffung aus mehreren Dateien zu unterstützen.Nehmen wir zum Beispiel Protokolldateien, die von vielen Protokollanalysatoren unterstützt werden, um Protokolldateien jeweils für einen Tag zu lesen.

EDIT

@san: Wenn Sie sagen, dass der verwendete Code nicht gesteuert werden kann, können Sie die einzelnen Dateien im laufenden Betrieb mithilfe von Named Pipes verketten:

$ mkfifo /tmp/cat
$ cat file1 file2 ... >/tmp/cat &
$ user_program /tmp/cat
...
$ rm /tmp/cat

Für 4 Dateien;xaa, xab, xac, xad eine schnelle Konzentration in Bash (als Wurzel):

losetup -v -f xaa; losetup -v -f xab; losetup -v -f xac; losetup -v -f xad

(Angenommen, loop0, loop1, loop2, loop3 sind die Namen der neuen Gerätedateien.)

Fügen Sie http://pastebin.com/PtEDQH7G in eine Skriptdatei "join_us" ein.Dann können Sie es folgendermaßen verwenden:

./join_us /dev/loop{0..3}

Dann (wenn es sich bei dieser großen Datei um einen Film handelt) können Sie einem normalen Benutzer den Besitz übertragen (chown itsme / dev / mapper / join) und er / sie kann ihn dann abspielen über: mplayer / dev / mapper / join

Die Bereinigung nach diesen (als root):

dmsetup remove joined; losetup -d /dev/loop[0123]

Nein, es gibt kein solches Tool oder Systemanruf.

Sie können untersuchen, ob es für jeden Prozess möglich ist, direkt in die endgültige Datei zu schreiben.Angenommen, Prozess 1 schreibt Bytes 0-X, Prozess 2 schreibt X-2X und so weiter.

Eine mögliche Alternative besteht darin, alle temporären Dateien in eine Named Pipe zu kopieren und diese Named Pipe dann als Eingabe für Ihr Programm mit nur einer Eingabe zu verwenden.Solange Ihr Programm mit einer Eingabe die Eingabe nur nacheinander liest und nicht sucht.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top