2010-01-03 14 views
8

Ich habe ein Programm, das Daten aus 2 Textdateien liest und speichern Sie das Ergebnis in eine andere Datei. Da es viele zu lesende und zu schreibende Daten gibt, die einen Leistungseinbruch verursachen, möchte ich die Lese- und Schreiboperationen parallelisieren.Wie parallel Datei lesen und schreiben

Mein erster Gedanke ist, verwenden Sie 2 Threads als Beispiel, ein Thread lesen/schreiben von Anfang an, und ein anderer Thread lesen/schreiben von der Mitte der Datei. Da meine Dateien als Zeilen und nicht als Bytes formatiert sind (jede Zeile kann unterschiedliche Datenbytes haben), funktioniert byteweise bei mir nicht. Und die Lösung, an die ich denken könnte, ist getline() zu verwenden, um die vorherigen Zeilen zuerst zu überspringen, was möglicherweise nicht effizient ist.

Gibt es eine gute Möglichkeit, eine bestimmte Zeile in einer Datei zu suchen? oder haben Sie noch andere Ideen, um das Lesen und Schreiben von Dateien zu paralisieren?

Umwelt: Win32, C++, NTFS, einzelne Festplatte

Dank.

-Dbger

+1

Was ist Ihr Dateisystem und welche Hardware verwenden Sie? Wenn Sie nur einen Controller/Datenträger haben, ist es unter Umständen nicht effizient, parallele E/A durchzuführen – Anycorn

+0

, also bedeutet das, dass Platten-I/O parallieren wird immer eine Leistungseinbuße verursachen, wenn nur auf dem gleichen Datenträger gelesen/geschrieben wird? –

+1

Dbger: Wenn Sie eine Festplatte verwenden, ja. – Mike

Antwort

18

Generell wollen Sie nicht Disk-I/O parallelisieren. Festplatten mögen keine zufällige I/O, weil sie ständig suchen müssen, um zu den Daten zu gelangen. Angenommen, Sie verwenden kein RAID, und Sie verwenden Festplatten im Gegensatz zu Solid-State-Speichern, werden Sie eine starke Leistungseinbuße feststellen, wenn Sie I/O parallelisieren (selbst wenn Sie Technologien wie diese verwenden, können Sie immer noch etwas Leistung sehen) Verschlechterung bei vielen zufälligen I/O).

Um Ihre zweite Frage zu beantworten, gibt es wirklich keine gute Möglichkeit, eine bestimmte Zeile in einer Datei zu suchen; Sie können nur explizit nach einem Byte-Offset mit der read Funktion suchen (siehe this page für weitere Details zur Verwendung.

+0

Also beim Lesen/Schreiben von Dateien kostet die Suche nach Platten die meiste Zeit, was in Multithreading-Umgebungen der Fall ist, ist das richtig? –

+2

Ja, Disk-Suchzeit ist im Allgemeinen der Engpass ist eine Multithread-I/O-Umgebung. Sie sollten versuchen, Ihre E/A zu serialisieren, wo es möglich ist. – Mike

+0

Danke Mike, nur zur Bestätigung, ist dies nur beim Lesen einer einzigen Datei oder auch beim Lesen mehrerer Dateien gelten (Thread 1 lesen file1, thread2 lesen file2) –

1

Dies ist nicht wirklich eine Antwort auf Ihre Frage, sondern ein Re-Design (das wir alle hassen kann aber nicht helfen.) Wie bereits erwähnt, wird es wahrscheinlich nicht helfen, E/A auf einer Festplatte mit mehreren Threads zu beschleunigen

Es könnte jedoch möglich sein, je nach Datenempfindlichkeit einen anderen Ansatz zu verwenden B. Durchsatzanforderungen, Datengröße usw. Es wäre nicht schwierig, eine Struktur im Speicher zu erstellen, die ein Bild der Daten verwaltet und einfache/schnelle Aktualisierungen der Textzeilen überall in den Daten ermöglicht. Sie könnten dann einen dedizierten Thread verwenden das überwacht einfach diese Struktur und wessen Aufgabe es ist zu schreiben die Daten auf die Festplatte. Das sequentielle Schreiben von Daten auf die Festplatte kann extrem schnell sein; es kann viel schneller sein, als zufällig nach verschiedenen Abschnitten zu suchen und es in Stücke zu schreiben.

+0

Wenn ich über 2M Daten sequentiell in eine Textdatei schreibe, kostet es ungefähr 1 Sekunde auf meinem Rechner, was für mich zu langsam ist. Um zu lesen, um eine Speicherstruktur der Datei zu bilden, muss ich die Daten zuerst lesen, was auch zu langsam ist, um meine Anforderung zu erfüllen. Ich würde jedoch die Themen zu Overlap-E/A und Memorymap-Datei untersuchen, um zu sehen, ob das hilft. –

+1

1 Sekunde, um 2MB zu schreiben? Das scheint erstaunlich langsam. Ich habe gerade einen Test durchgeführt, der 10M in 100ms in eine Datei schreibt, und mein PC ist keine echte Geschwindigkeitsmaschine (3.2GHz und ich denke * 7200rpm Laufwerk). Mit welchen APIs öffnen und schreiben Sie in die Datei? –

+0

Ich verwende std :: ofstream, um viele getrennte Daten in einer Schleife zu speichern. wie "für (...) {streamOut << x; streamOut << y}", und ich habe auch eine 7200rpm Laufwerk mit einem Dual-Core 2,16 GHz CPU –

2

Das Einreihen mehrerer Lese- und Schreibvorgänge hilft nicht, wenn Sie auf einem Datenträger ausgeführt werden. Wenn Ihre App auch eine Menge Arbeit in der CPU ausgeführt hat, könnten Sie Ihre Lese- und Schreibvorgänge asynchron ausführen und die CPU arbeiten lassen, während die Festplatten-E/A im Hintergrund auftritt. Alternativ erhalten Sie eine zweite physikalische Festplatte: lesen Sie von einem, lesen Sie den anderen. Für kleine Datenmengen ist das oft effektiv und ziemlich viel billiger als das Schreiben von Code.

+0

Verwenden Sie einen Backgroud-Thread, um die Ausgabedaten nach und nach zu schreiben, wenn die CPU mit der Berechnung beschäftigt ist. Dies ist eine gute Idee. Aber zum Lesen gibt es nicht viel Arbeit, da die Daten nicht bereit sind. –

+0

Dbger, es hängt von der Art Ihrer Daten ab. Wenn Sie in der Lage sind, einen zweiten asynchronen Abruf in die Warteschlange einzureihen, der während der Verarbeitung der Daten des ersten Abrufs erfüllt wird, sind Sie im Geschäft. Auch hier ist es am effektivsten, wenn die Festplatte nicht mit anderen I/O-Operationen beschäftigt ist, was möglicherweise nicht auf Ihre unmittelbare Situation zutrifft. –