Schnellstes Lesen von Dateien in einer Multithread-Anwendung

8

Ich muss eine 8192x8192 Matrix in den Speicher lesen. Ich möchte es so schnell wie möglich machen.
Im Moment habe ich diese Struktur:

%Vor%

In der Funktion ParallelRead parse ich jede Zeile, mache atoi und bearbeite die Matrix. Die Parallelität ist zeilenweise wie der Thread t parses line t, t+ 1 * NUM_THREADS..

Bei einem Zweikernsystem mit 2 Threads dauert dies

%Vor%

Gibt es eine Möglichkeit, dies noch weiter zu optimieren?

    
sud03r 20.05.2012, 19:02
quelle

4 Antworten

22

Es ist eine schlechte Idee, es so zu machen. Threads können mehr CPU-Zyklen erhalten, wenn Sie genügend Kerne haben, aber immer noch nur eine Festplatte haben. Daher können Threads die Geschwindigkeit beim Lesen von Dateidaten nicht verbessern.

Sie machen es tatsächlich viel schlimmer. Das Lesen von Daten aus einer Datei erfolgt am schnellsten, wenn Sie sequenziell auf die Datei zugreifen. Dies minimiert die Anzahl der Lesekopf-Suchvorgänge, bei weitem die teuerste Operation auf einem Plattenlaufwerk. Indem Sie den Messwert über mehrere Threads verteilen, die jeweils einen anderen Teil der Datei lesen, lassen Sie den Leserkopf ständig vor- und zurückspringen. Sehr, sehr schlecht für den Durchsatz.

Verwenden Sie nur einen -Thread, um Dateidaten zu lesen. Sie können es möglicherweise mit einigen Rechenzyklen für die Dateidaten überlappen, indem Sie einen Thread starten, sobald ein Teil der Dateidaten geladen ist.

Do Achten Sie auf den Testeffekt. Wenn Sie Ihr Programm erneut ausführen, in der Regel nachdem Sie Ihren Code etwas optimiert haben, ist es wahrscheinlich, dass das Programm Dateidaten im Dateisystemcache wiederfinden kann, so dass es nicht von der Festplatte gelesen werden muss. Das ist sehr schnell, Speicherbusgeschwindigkeit, eine Speicher-zu-Speicher-Kopie. Sehr wahrscheinlich auf Ihrem Dataset, da es nicht sehr groß ist und leicht in den Arbeitsspeicher einer modernen Maschine passt. Dies geschieht (typischerweise) nicht auf einer Produktionsmaschine. Seien Sie also sicher, den Cache zu leeren, um realistische Zahlen zu erhalten, was auch immer Ihr Betriebssystem braucht.

    
Hans Passant 20.05.2012 20:49
quelle
2

Es lohnt sich, zwei kleinere Eingabepuffer zu reservieren (sagen wir, dass sie jeweils 200 Zeilen umfassen).

Dann muss ein Thread Daten in die Eingabepuffer lesen. Wenn ein Eingabepuffer voll ist, übergeben Sie ihn an einen zweiten Thread, der die Analyse durchführt. Dieser zweite Thread könnte einen Thread-Pool für das gleichzeitige Parsen verwenden (check openMP).

Sie müssen Sperren / Mutexe verwenden, um sicherzustellen, dass jeder Thread exklusiven Zugriff hat.

Dies wäre besser, weil das Parsing jetzt gleichzeitig mit dem Lesen der Datei erfolgt und Ihr Speicherzugriff auf den Puffer eher lokal ist und in Ihren CPU-Cache passt. Dies kann die Lese- und Parsing-Geschwindigkeit verbessern.

Wenn fgets der Flaschenhals ist, können Sie die Datei auch als Binärdatei in den Speicher einlesen. Dies könnte die Lesegeschwindigkeit verbessern, erfordert jedoch zusätzliches Parsing und erschwert die Durchführung der oben genannten Optimierung.

    
user180326 20.05.2012 19:58
quelle
2

Probieren Sie einen übergeordneten Thread aus, der das Character-Array mit etwas wie fread lädt, um alles in 1 io als eine große Zeichenfolge zu laden.

Lassen Sie den Eltern die Zeichenfolge folgen und eine Zeile finden oder berechnen Sie, wo die erste Zeile auf Größen basiert. Übergeben Sie die Verarbeitung dieser Zeile an einen Thread. Nächste Zeile, Spülen, Wiederholen bis EOF. Synchronisieren Sie mit den Threads. Fertig.

    
EvilTeach 20.05.2012 20:30
quelle
1

Die beste Leistung, die Sie mit Datei-I / O erzielen können, ist die Speicherzuordnung. Dies ist ein Beispiel . Ich würde von einem Single-Thread-Design ausgehen, und wenn sich die Post-Load-Verarbeitung als Flaschenhals erweist, sollte man parallel vorgehen.

    
bobah 20.05.2012 20:33
quelle

Tags und Links