std :: ifstream Puffer-Caching

8

In meiner Anwendung versuche ich sortierte Dateien zusammenzuführen (sortiere sie natürlich), also muss ich jedes Element in beiden Dateien durchlaufen, um das minimale in das dritte zu schreiben. Bei großen Dateien funktioniert das ziemlich langsam, soweit ich keine andere Wahl sehe (die Iteration muss durchgeführt werden). Ich versuche, das Laden von Dateien zu optimieren. Ich kann eine gewisse Menge an RAM verwenden, die ich für die Pufferung verwenden kann. Ich meine, anstatt 4 Bytes aus beiden Dateien jedes Mal zu lesen, wenn ich einmal etwas wie 100 MB lesen kann und danach mit diesem Puffer arbeite, bis es kein Element im Puffer gibt, werde ich den Puffer wieder auffüllen. Aber ich denke, Ifstream macht das schon, wird es mir mehr Leistung bringen und gibt es einen Grund dafür? Wenn fstream tut, kann ich vielleicht die Größe dieses Puffers ändern?

hinzugefügt

Mein aktueller Code sieht so aus (Pseudocode)

%Vor%

Was ich hier nicht mag, ist

  • seek_back - Ich muss zurück zur vorherigen Position suchen, da es keine Möglichkeit gibt, 4 Bytes zu sehen
  • zu viel Lesen von Datei
  • Wenn einer der Streams in EOF ist, überprüft er weiterhin diesen Stream, anstatt den Inhalt eines anderen Streams direkt auszugeben, aber das ist kein großes Problem, da die Chunk-Größen fast immer gleich sind.

Können Sie eine Verbesserung vorschlagen?

Danke.

    
ledokol 29.12.2010, 21:35
quelle

6 Antworten

5

Ohne in die Diskussion der Stream-Puffer einzusteigen, können Sie seek_back loswerden und den Code im Allgemeinen vereinfachen, indem Sie Folgendes tun:

%Vor%

Bearbeiten:

Hinzugefügt binäre Fähigkeit

%Vor%     
davka 30.12.2010 08:57
quelle
3

In absteigender Reihenfolge der Leistung (am besten zuerst):

  • Speicherbelegte E / A
  • Betriebssystemspezifische ReadFile oder read Aufrufe.
  • fread in einen großen Puffer
  • ifstream.read in einen großen Puffer
  • ifstream und Extraktoren
Ben Voigt 29.12.2010 22:28
quelle
2

Ein Programm wie dieses sollte I / O-gebunden sein, was bedeutet, dass es mindestens 80% seiner Zeit damit verbringen sollte, einen Puffer zu lesen oder zu schreiben, und wenn die Puffer ziemlich groß sind, sollte es die Platte behalten Köpfe beschäftigt. Das ist was du willst.

Gehen Sie nicht davon aus, dass es I / O-gebunden ist, ohne Beweis. Ein Weg, um es zu beweisen, ist, indem man mehrere Stapelaufnahmen . Wenn dies der Fall ist, zeigen die meisten Beispiele, dass das Programm auf den Abschluss der E / A wartet.

Es ist möglich, dass es nicht I / O-gebunden ist, was bedeutet, dass Sie in einigen Samples andere Dinge finden, die Sie nie erwartet haben. Wenn ja, dann weißt du, was zu beheben ist, um es zu beschleunigen. Ich habe gesehen, dass ein Code wie dieser viel mehr Zeit in der Merge-Schleife verbraucht als zum Beispiel das End-of-File testet, Daten vergleicht usw. usw.

    
Mike Dunlavey 30.12.2010 02:26
quelle
0

Sie können einfach die Lesefunktion eines ifstream verwenden, um große Blöcke zu lesen.

Ссылка

Der zweite Parameter ist die Anzahl der Bytes. Sie sollten in Ihrem Fall ein Vielfaches von 4 machen - vielleicht 4096? :)

Lies einfach ein Stück nach dem anderen und arbeite daran.

Wie Martin-york sagte, kann dies keinen positiven Effekt auf Ihre Leistung haben, aber versuchen Sie es und finden Sie es heraus.

    
Hank 29.12.2010 22:23
quelle
0

Ich denke, dass es sehr wahrscheinlich ist, dass Sie die Leistung verbessern können, indem Sie große Stücke lesen.

Versuchen Sie, die Datei mit ios::binary als Argument zu öffnen, und verwenden Sie dann istreamream_read um die Daten zu lesen.

Wenn Sie maximale Leistung benötigen, würde ich vorschlagen, Iostreams ganz zu überspringen und statt dessen cstdio zu verwenden. Aber ich denke, das ist nicht das, was du willst.

    
Johan Kotlinski 29.12.2010 22:25
quelle
0

Wenn Ihre Daten nicht sehr speziell sind, ist es unwahrscheinlich, dass Sie die Pufferung verbessern, die in das std :: fstream-Objekt eingebaut ist.

Die std :: fstream-Objekte sind so konzipiert, dass sie für den allgemeinen Dateizugriff sehr effektiv sind. Es klingt nicht so, als würden Sie etwas Spezielles tun, indem Sie auf die Daten 4 Bytes gleichzeitig zugreifen. Sie können Ihren Code immer profilieren, um zu sehen, wo die tatsächliche Zeit in Ihrem Code verbracht wird.

Vielleicht können Sie, wenn Sie den Code mit anderen teilen, größere Ineffizienzen feststellen.

Bearbeiten:

Ich mag deinen Algorithmus nicht. Das Suchen vorwärts und vorwärts kann auf dem Strom schwer sein besonders der Zahl liegt über einer Puffergrenze. Ich würde immer nur eine Zahl durch die Schleife lesen.

Versuche das:
Hinweis: Dies ist nicht optimal (und es geht davon aus, Stream-Eingabe von Zahlen (während Ihres sieht binär)) Aber ich bin sicher, dass Sie es als Ausgangspunkt verwenden können.

%Vor%     
Martin York 29.12.2010 22:04
quelle