I / O-Strategien für Rechenprobleme mit großen Datenmengen?

15

Meine Forschungsgruppe konzentriert sich auf die Molekulardynamik, die offensichtlich als Teil einer einzelnen Flugbahn Gigabyte an Daten erzeugen kann, die dann analysiert werden müssen.

Einige der Probleme, mit denen wir uns befassen, betreffen Korrelationen im Datensatz. Dies bedeutet, dass wir große Datenmengen im Speicher verfolgen und analysieren müssen, anstatt einen sequentielleren Ansatz zu verwenden.

Was ich wissen möchte, ist, was die effizientesten Strategien zum Behandeln von E / A von großen Datensätzen in Skripten sind. Normalerweise verwenden wir Python-basierte Skripte, weil das Codieren der Datei-E / A weniger schmerzhaft ist als bei C oder Fortran. Wenn jedoch Dutzende oder Hunderte von Millionen Zeilen verarbeitet werden müssen, ist nicht klar, was der beste Ansatz ist . Sollten wir erwägen, den Dateieingabeteil des Codes in C auszuführen, oder ist eine andere Strategie sinnvoller? (Wird es besser sein, das gesamte Array einfach vorab in den Speicher zu laden, als eine Reihe aufeinanderfolgender Lesevorgänge von "Chunks" (in der Größenordnung von Megabyte)?

Einige zusätzliche Hinweise:

  • Wir suchen in erster Linie nach Skriptwerkzeugen für die Nachbearbeitung und nicht nach "Online" -Tools - daher die Verwendung von Python.

  • Wie oben erwähnt, führen wir MD-Simulationen durch. Ein interessantes Thema sind Diffusionsberechnungen, für die wir den Einstein-Diffusionskoeffizienten erhalten müssen: Dies bedeutet, dass wir wirklich alle Daten in den Speicher laden müssen, bevor wir mit der Berechnung beginnen - alle Datenblöcke ( Aufzeichnungen einzelner Zeiten) werden miteinander interagieren.

    D=16limΔt(x(t+Δt)-x(t))2
aeismail
quelle

Antworten:

6

Ich gehe davon aus, dass Ihre Frage aus der Beobachtung stammt, dass die E / A einen erheblichen Overhead in Ihrer gesamten Analyse verursacht. In diesem Fall können Sie versuchen, die E / A mit der Berechnung zu überlappen.

Ein erfolgreicher Ansatz hängt davon ab, wie Sie auf die Daten zugreifen und welche Berechnungen Sie für diese Daten durchführen. Wenn Sie ein Muster identifizieren können oder der Zugriff auf verschiedene Bereiche der Daten im Voraus bekannt ist, können Sie versuchen, die "nächsten Datenblöcke" im Hintergrund vorab abzurufen, während Sie die "aktuellen Datenblöcke" verarbeiten.

Wenn Sie beispielsweise Ihre Datei nur einmal durchlaufen und jede Zeile oder jeden Zeilensatz verarbeiten, können Sie den Stream in Zeilenblöcke (oder MB) aufteilen. Dann können Sie bei jeder Iteration über die Chunks Chunk i + 1 laden, während Sie Chunk i verarbeiten.

Ihre Situation ist möglicherweise komplexer und erfordert komplexere Lösungen. In jedem Fall besteht die Idee darin, die E / A im Hintergrund auszuführen, während der Prozessor über Daten verfügt, an denen gearbeitet werden kann. Wenn Sie weitere Details zu Ihrem spezifischen Problem angeben, können wir uns möglicherweise eingehender damit befassen;)

---- Erweiterte Version nach Angabe weiterer Details ----

Ich bin mir nicht sicher, ob ich die Notation verstehe, aber wie Sie sagten, ist die Idee eine All-in-All-Interaktion. Sie erwähnen auch, dass die Daten möglicherweise in den Arbeitsspeicher passen. Dann würde ich damit beginnen, die Zeit zum Laden aller Daten und die Zeit zum Durchführen der Berechnung zu messen. Jetzt,

  • Wenn der Prozentsatz der E / A niedrig ist (niedrig, da Sie sich nicht um den Overhead kümmern, unabhängig davon, was er ist: 0,5%, 2%, 5%, ...), verwenden Sie einfach den einfachen Ansatz: Daten laden sofort und berechnen. Sie sparen Zeit für weitere interessante Aspekte Ihrer Forschung.

  • Wenn Sie sich den Aufwand nicht leisten können, sollten Sie sich überlegen, was Pedro vorgeschlagen hat. Denken Sie daran, was Aron Ahmadia erwähnt hat, und testen Sie es, bevor Sie eine vollständige Implementierung durchführen.

  • Wenn die vorherigen nicht zufriedenstellend sind, würde ich mich für eine Out-of-Core- Implementierung entscheiden [1]. Da es so aussieht, als würden Sie Berechnungen mit Daten durchführen, gibt es Hoffnung :) Einige Pseudocodes (vorausgesetzt, die Ergebnisse Ihrer Analyse passen in den Arbeitsspeicher):n2n

    Laden Sie chunk1 und chunk2
    für Chunks ist i = 1 bis n
        Laden Sie den Block i + 1 asynchron
        für Chunks in j = i + 1 bis n
            Laden Sie den Block j + 1 asynchron
            Rechne mit den Chunks i, j (* für die erste Iteration sind dies die vorinstallierten Chunks 1 und 2 *)

Hinweis: Dies ist ein schneller und unsauberer Pseudocode. Man müsste die Indizes anpassen.

Um dies zu implementieren, ist es üblich, die sogenannte Doppelpufferung zu verwenden . Grob gesagt: Teilen Sie das Gedächtnis in zwei Arbeitsbereiche; Während Daten im Hintergrund in Arbeitsbereich 1 geladen werden, berechnet der Prozessor mit den Daten in Arbeitsbereich 2. Tauschen Sie bei jeder Iteration die Rolle aus.

Es tut mir leid, dass ich momentan keine gute Referenz finden kann.

[1] Ein Out-of-Core-Algorithmus enthält einen Mechanismus zum (effizienten) Behandeln von Daten, die sich auf der Festplatte befinden. Sie werden im Gegensatz zu In-Core ("In-RAM") als Out-of-Core bezeichnet.

Diego
quelle
7

Ich hatte zuvor mit ähnlichen Problemen zu kämpfen, und meine Lieblingslösung ist die Verwendung von speicherabgebildeten E / A , wenn auch in C ...

Das Prinzip dahinter ist ganz einfach: Anstatt eine Datei zu öffnen und daraus zu lesen, laden Sie sie direkt in den Speicher und greifen darauf zu, als wäre es ein riesiges Array. Der Trick, der es effizient macht, besteht darin, dass das Betriebssystem die Datei nicht tatsächlich lädt , sondern sie nur wie ausgelagerten Speicher behandelt , der geladen werden muss. Wenn Sie auf ein bestimmtes Byte in Ihrer Datei zugreifen, wird die Speicherseite für diesen Teil der Datei in den Speicher ausgelagert. Wenn Sie weiterhin auf verschiedene Teile der Datei zugreifen und der Speicher knapp wird, werden die weniger genutzten Teile automatisch ausgetauscht.

Eine schnelle Google-Suche zeigt mir, dass dies auch für Python verfügbar ist: 16.7. mmap - Speicherabgebildete Dateiunterstützung , aber ich weiß nicht genug über Python, um festzustellen, ob es wirklich dasselbe ist.

Pedro
quelle
1
Stellen Sie einfach sicher, dass Sie messen und testen, bevor Sie so etwas mmapin Ihren Hauptcode implementieren . Viele moderne Betriebssysteme bieten eine ähnliche Leistung readbei weniger Komplikationen. (Außerdem bietet mmap in Python eine portable Schnittstelle zu den Windows- und UNIX-Speicherzuordnungen.)
Aron Ahmadia
1

Vielleicht können Sie Cython in Ihren Datei-E / A-Abschnitten verwenden und dieses Teil in C-Code konvertieren?

asmatisch
quelle