2009-06-18 4 views
5

Ich arbeite an einem Stück wissenschaftlicher Software, die sehr CPU-intensiv ist (ihre Proc gebunden), aber es muss Daten ziemlich oft auf Festplatte schreiben (i/o gebunden).Effiziente Möglichkeit, Daten auf dem Datenträger zu speichern, während eine rechenintensive Aufgabe ausgeführt wird

Ich bin Parallelisierung zu diesem hinzufügen (OpenMP) und ich frage mich, was der beste Weg, um die Write-to-Disk-Bedürfnisse zu adressieren. Es gibt keinen Grund, warum die Simulation auf der Festplatte warten sollte (was sie gerade macht).

Ich bin auf der Suche nach einer "Best Practice" dafür, und Geschwindigkeit ist das, was mir am wichtigsten ist (das können sehr lange Simulationen sein).

Dank ~ Alex

Erste Gedanken:

einen separaten Prozess mit tun, um die eigentliche Schreiben auf die Festplatte, so dass die Simulation zwei Prozesse hat: eine CPU-bound (Simulation) und ist IO-bound (Datei schreiben). Das klingt kompliziert.

Möglicherweise ein Rohr/Puffer? Ich bin etwas neu bei diesen, also könnte das eine mögliche Lösung sein.

Antwort

2

Wenn Sie OpenMP zu Ihrem Programm Umsetzung dann ist es besser #pragma omp Einzel oder #pragma omp Master von parallelem Abschnitt zu verwenden, um eine Datei zu speichern. Diese Pragmas erlauben nur einem Thread, etwas auszuführen. So können Sie Code aussieht wie folgt:

#pragma omp parallel 
{ 
    // Calculating the first part 
    Calculate(); 

    // Using barrier to wait all threads 
    #pragma omp barrier 

    #pragma omp master 
    SaveFirstPartOfResults(); 

    // Calculate the second part 
    Calculate2(); 

    #pragma omp barrier 

    #pragma omp master 
    SaveSecondPart(); 

    Calculate3(); 

    // ... and so on 
} 

Hier Team von Threads Berechnung tun, sondern nur einzelner Thread Ergebnisse auf der Festplatte speichern.

Es sieht wie Software-Pipeline aus. Ich empfehle Ihnen, tbb :: pipeline pattern aus der Intel Threading Building Blocks-Bibliothek zu betrachten. Ich verweise Sie auf das Tutorial zu Software-Pipelines unter http://cache-www.intel.com/cd/00/00/30/11/301132_301132.pdf#page=25. Bitte lesen Sie Abschnitt 4.2. Sie lösten das Problem: ein Thread zum Lesen vom Laufwerk, ein zweiter zum Lesen von Strings, der dritte zum Speichern auf Laufwerk.

5

Ich würde sagen, der beste Weg wäre, einen anderen Thread zu spawnen, um die Daten zu speichern, nicht ein völlig neuer Prozess; Bei einem neuen Prozess müssen Sie die Daten, die über die Prozessgrenze gespeichert werden sollen, kommunizieren, was zu neuen Schwierigkeiten führt.

0

Ein Thread führt kontinuierlich einen Schritt des rechenintensiven Prozesses aus und fügt dann das Teilergebnis einer Reihe von Teilergebnissen hinzu. Ein anderer Thread entfernt kontinuierlich Teilergebnisse aus der Warteschlange und schreibt sie auf die Festplatte. Stellen Sie sicher, dass der Zugriff auf die Warteschlange synchronisiert ist. Eine Warteschlange ist eine listenähnliche Datenstruktur, in der Sie Elemente zum Ende hinzufügen und Elemente von vorne entfernen können.

1

Da Sie CPU und IO gebunden sind: Lassen Sie mich raten: Es ist noch genügend Speicher vorhanden, oder?

Wenn dies der Fall ist, sollten Sie die Daten, die in einem bestimmten Umfang auf die Festplatte geschrieben werden sollen, zwischenspeichern. Das Schreiben großer Datenmengen ist normalerweise viel schneller als das Schreiben kleiner Teile.

Für das Schreiben selbst: Erwägen Sie die Verwendung von Memory-Mapped IO. Es ist eine Weile her, seit ich Benchmarks gemacht habe, aber beim letzten Mal war es deutlich schneller.

Auch Sie können immer von CPU vs IO ein bisschen handeln. Ich denke, Sie schreiben gerade die Daten als eine Art roher, unkomprimierter Daten, richtig? Sie können eine gewisse IO-Leistung erzielen, wenn Sie ein einfaches Komprimierungsschema verwenden, um die Menge der zu schreibenden Daten zu reduzieren. Die ZLIB-Bibliothek ist ziemlich einfach zu bedienen und komprimiert sehr schnell auf der niedrigsten Komprimierungsstufe. Es hängt von der Art Ihrer Daten ab, aber wenn es eine Menge Redundanz gibt, kann sogar ein sehr primitiver Komprimierungsalgorithmus das IO-gebundene Problem beseitigen.

3

Die erste Lösung, die Ihnen in den Sinn kommt, ist ziemlich genau das, was Sie gesagt haben - die Festplatte schreibt in ihrem eigenen Prozess mit einer Einwegleitung vom Sim zum Schreiber. Der Schreiber schreibt so schnell wie möglich (neue Daten werden aus der Pipe gezogen). Das Problem damit ist, dass, wenn die Sim zu weit vor dem Schreiber kommt, die Sim sowieso auf den Pipe-Schreibvorgängen blockiert wird, und sie wird bei einer Entfernung I/O-gebunden sein.

Das Problem ist, dass in der Tat ist Ihr Simulationszyklus nicht abgeschlossen, bis es die Ergebnisse ausspuckt.

Die zweite Sache, die mir einfällt, ist die Verwendung nicht blockierender E/A.Immer wenn die Sim schreiben muss, sollte dies über nicht blockierende E/A geschehen. Beim nächsten Schreibvorgang kann er dann die Ergebnisse der vorherigen E/A-Operation (möglicherweise mit einer kleinen Wartezeit) aufheben, bevor er die neue startet. Dadurch wird die Simulation so lange wie möglich parallel zur E/A ausgeführt, ohne dass die Simulation dem Schreiben sehr weit voraus ist.

Die erste Lösung wäre besser, wenn der Simulationsverarbeitungszyklus variiert (manchmal kleiner als die Zeit für einen Schreibvorgang, manchmal länger), weil die Schreibvorgänge im Durchschnitt mit dem Sim Schritt halten könnten.

Wenn der Verarbeitungszyklus immer (oder fast immer) kürzer ist als die Schreibzeit , dann können Sie sich auch nicht mit der Pipe beschäftigen und nur nicht blockierende E/A verwenden, da Sie die Pipe verwenden es wird sich irgendwann füllen und die Sim wird sowieso auf der I/O hängen.

+0

Ich denke die 1-Wege-Leitung ist der Weg, den ich dann gehen werde. Ich glaube nicht, dass ich auf das Problem stoßen werde, zu sehr zu blockieren; Da nicht viele Daten generiert werden, wollte ich nur die Threads trennen. Wenn ich so viele Daten generieren würde, würde ich überdenken, wie viel tatsächlich aufbewahrt werden muss. – machinaut

0

Machen Sie Ihre Anwendung zwei Threads, eine für CPU und eine für die Festplatte.

Haben die CPU-Thread Push-Daten in eine Warteschlange abgeschlossen, die die Festplatte Faden zieht ab dann als Daten kommen.

diese Weise kann die CPU wird nur die Daten befreit und läßt jemand anderes damit umgehen und die harte Laufwerk wartet nur geduldig auf Daten in der Warteschlange.

Implementation weise, könnten Sie die Warteschlange als Shared Memory-Typ von Objekt, aber ich denke, eine Rohrleitung wäre genau das, was Sie suchen würden. Die CPU schreibt bei Bedarf einfach in die Pipe. Auf der Seite der Festplatte würden Sie nur die Pipe lesen und von dort aus, wann immer Sie gültige Daten haben.

Verwandte Themen