2012-05-20 3 views
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:Schnellste Datei lesen in einer Multi-Thread-Anwendung

char inputFile[8192][8192*4]; // I know the numbers are at max 3 digits 
int8_t matrix[8192][8192]; // Matrix to be populated 

// Read entire file line by line using fgets 
while (fgets (inputFile[lineNum++], MAXCOLS, fp)); 

//Populate the matrix in parallel, 
for (t = 0; t < NUM_THREADS; t++){ 
    pthread_create(&threads[t], NULL, ParallelRead, (void *)t); 
} 

In der Funktion ParallelRead, ich analysiere jede Zeile, tue atoi und die Matrix besiedeln. Die Parallelität ist zeilenweise wie Gewinde t Linie parst t, t+ 1 * NUM_THREADS..

auf einem Zwei-Kern-System mit 2 Fäden, dies nimmt

Loading big file (fgets) : 5.79126 
Preprocessing data (Parallel Read) : 4.44083 

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

+3

Vielleicht könnten Sie die Befüllung von Threads parallel zur E/A starten, da genügend Daten verfügbar sind. – vanza

+0

Um ehrlich zu sein, bin ich ein wenig überrascht, dass es Ihnen gelungen ist, * irgendeine * Leistungsverbesserung durch das Lesen der gleichen Datei aus mehreren Threads zu erzielen ... Stellen Sie beim Benchmarking sicher, dass die Datei tatsächlich von der Festplatte gelesen wird nicht aus dem Cache? – NPE

+0

@aix Ich habe 2 Threads nur zum Beispiel verwendet. Ich habe den Vorverarbeitungsteil parallelisiert, nachdem die Daten in den Speicher gelesen wurden. – sud03r

Antwort

2

Eine Sache, die in Betracht gezogen werden sollte, ist die Zuweisung von zwei kleineren Eingangspuffern (sagen wir, dass sie jeweils 200 Zeilen sein werden).

Dann haben ein Thread lesen Daten in die Eingabepuffer. 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 Parsen 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 Engpass 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.

2

Versuchen Sie einen übergeordneten Thread, der das Zeichen-Array lädt, indem Sie etwas wie fread verwenden, um alles in 1 io als eine große große Zeichenfolge zu laden.

Lassen Sie die Eltern die Zeichenfolge durchgehen 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. Erledigt.

1

Die beste Leistung, die Sie mit Datei-E/A erzielen können, ist die Speicherzuordnung. This is an example. Ich würde von einem Single-Thread-Design ausgehen und wenn sich die Post-Load-Verarbeitung als Flaschenhals erweist, sollte man parallel vorgehen.

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 auf den Test-Effekt achten.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 Datensatz, da es nicht sehr groß ist und leicht in den Arbeitsspeicher einer modernen Maschine passt. Dies geschieht (typischerweise) nicht auf einer Produktionsmaschine. Stellen Sie also sicher, dass Sie den Cache leeren, um realistische Zahlen zu erhalten, was auch immer Ihr Betriebssystem benötigt.

+2

er _not_ die Datei nicht parallel liest, konvertiert er die Zeichenfolge parallel aus dem Speicher in int8_t's. Daran ist nichts falsch. – kratenko

+0

Ich behauptete nie, dass irgendetwas daran falsch war. Ich empfehle, das mit dem Thread zu überlappen, der die Daten liest. –