std::ifstream Puffer-caching
In meiner Anwendung, die ich bin versucht zu verschmelzen sortiert Dateien (halten Sie sortiert natürlich), also habe ich Durchlaufen jedes element in beiden Dateien zu schreiben, die minimal die Dritte. Das funktioniert ziemlich langsam bei großen Dateien, so weit ich sehe keine andere Wahl (die iteration gemacht werden muss), die ich versuche zu optimieren-Datei laden. Ich kann eine Menge an RAM, die ich benutzen kann für die Pufferung. Ich meine zu Lesen, anstatt 4 bytes aus den beiden Dateien jedes mal, wenn ich Lesen kann, sobald etwas wie 100Mb und die Arbeit mit, dass die Puffer nach, bis es kein element in den Puffer, dann habe ich werde füllen Sie den Puffer wieder. Aber ich denke, ifstream ist bereits das tun, wird es mir mehr Leistung und gibt es einen Grund? Wenn fstream sind macht, vielleicht kann ich ändern Größe der Puffer?
Hinzugefügt
Mein Aktueller code sieht so aus (pseudocode)
//this is done in loop
int i1 = input1.read_integer();
int i2 = input2.read_integer();
if (!input1.eof() && !input2.eof())
{
if (i1 < i2)
{
output.write(i1);
input2.seek_back(sizeof(int));
} else
input1.seek_back(sizeof(int));
output.write(i2);
}
} else {
if (input1.eof())
output.write(i2);
else if (input2.eof())
output.write(i1);
}
Was ich nicht mag, ist hier
- seek_back - ich habe, zu suchen zurück zur vorherigen position, da es keine Möglichkeit gibt, peek 4 bytes
- zu viel beim Lesen der Datei
- wenn einer der Ströme in EOF-es geht immer noch weiter, um zu überprüfen, dass der Strom, anstatt Inhalte von anderen Strom direkt zum Ausgang, aber das ist kein großes Problem, da die chunk-Größen sind fast immer gleich.
Können Sie vorschlagen, eine Verbesserung für das?
Dank.
- Wie Plattform-spezifische willst du? Verschiedene Plattformen können Sie Hinweise zu den OS-Kernel, um es zu bekommen um den job zu erledigen schneller-aber natürlich auch diejenigen, die gehen, um Plattform-spezifische.
- Ich möchte nicht, um alle Plattform-spezifischen code gibt. Ist es vernünftig zu implementieren Pufferung?
- Dann mein Vorschlag ist, zu versuchen, das caching selbst und sehen Sie, ob es einen Unterschied macht. Ohne auf die kernel-obwohl es natürlich nicht so schnell wie möglich. (Zum Beispiel, unter Windows würde man pass
FILE_FLAG_SEQUENTIAL_SCAN
für eine workload so) - Unter Windows würde man auch verwenden
MapViewOfFile
. Auf *nixfadvise
undmmap
. - Da ist ein Fehler in deinem code. (Was ist, wenn beide Ströme erreichen EOF zur gleichen Zeit?)
- Dann nichts geschrieben wird ausgegeben und es wird der loop verlassen.
- Hinzugefügt Pufferung und entfernt suchen Algorithmus, derzeit funktioniert viel besser. Vielen Dank an alle.
- Sie können beide erreichen ein EOF-Zeichen an der gleichen Zeit. Als er nicht eine seek_back auf einem Datenstrom jedes mal.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ohne sich in die Diskussion über stream puffert, können Sie loszuwerden, die
seek_back
und in der Regel machen den code sehr viel einfacher durch machen:Edit:
Hinzugefügt binäre Funktion
In absteigender Reihenfolge der Leistung (beste zuerst):
ReadFile
oderread
Anrufe.fread
in einen großen Pufferifstream.read
in einen großen Pufferifstream
und Abzieheropen
/read
/close
ist fast universell tragbar, als auch, noch auf Windows.stdio.h
ist Teil der C++ - standard-Bibliothek. Du hast Recht, es ist auch ein Teil der C-standard-Bibliothek. In Ihrem letzten Kommentar sagte Sie, Sie brauchte etwas "portable" und " POSIX ist sehr portabel. Schließlich, ja, es ist ein großer großer GROßER Unterschied in der Leistung zwischen stdio-API undfstream
.Einem Programm wie diesem sollte die E/A-gebunden, d.h. Sie ausgeben sollten mindestens 80% der Zeit mit dem warten auf die Fertigstellung von schreiben und Lesen, einen Puffer, und wenn die Puffer sind Recht groß, Sie sollten halten Sie die Festplatte Köpfe beschäftigt. Das, was Sie wollen.
Nicht davon ausgehen, es ist I/O-gebunden, ohne Beweis. Ein Weg, um es zu beweisen ist, indem Sie mehrere stackshots. Wenn Sie es ist, die meisten der Proben wird zeigen, das Programm wartet auf I/O-Abschluss.
Ist es möglich, dass es nicht I/O-gebunden, das heißt, Sie finden vielleicht andere Dinge, die sich in einigen der Proben, die Sie nie erwartet. Wenn ja, dann wissen Sie, was zu korrigieren ist, um ihn zu beschleunigen. Ich habe gesehen, einige code wie diesem verbringen viel mehr Zeit als nötig in der merge-loop-Tests für die end-of-Datei, um Daten zu vergleichen, etc.. zum Beispiel.
Können Sie einfach verwenden Sie die read-Funktion eines ifstream zum Lesen von großen Blöcken.
http://www.cplusplus.com/reference/iostream/istream/read/
Der zweite parameter ist die Anzahl der bytes. Sollte man diese ein Vielfaches von 4 ist in Ihrem Fall - vielleicht 4096? 🙂
Lesen Sie einfach ein Stück zu einer Zeit und Arbeit auf Sie zu.
Als martin-york, sagte, dies kann nicht haben keine positive Wirkung auf Ihre Leistung, aber versuchen Sie es und finden Sie heraus.
Ich denke, es ist sehr wahrscheinlich, dass Sie die Leistung verbessern können, durch das Lesen großen Brocken.
Versuchen, öffnen Sie die Datei mit
ios::binary
als argument, dann verwenden Sie istream::read, die Daten zu Lesen.Wenn Sie benötigen maximale Leistung, würde ich tatsächlich vorschlagen, überspringen iostreams insgesamt, und mit cstdio statt. Aber ich denke, das ist nicht, was Sie wollen.
Es sei denn, es ist etwas ganz besonderes über Ihre Daten ist es unwahrscheinlich, dass Sie eine Verbesserung der Pufferung, der in der std::fstream sind Objekt.
Std::fstream sind Objekte, die entworfen sind, um sehr effiziente für Allgemeine Datei-Zugriff. Es klingt nicht wie Sie sind, tut nichts besonderes durch den Zugriff auf die Daten 4 Byte zu einem Zeitpunkt. Sie können immer Profilieren Sie Ihren code, um zu sehen, wo der tatsächliche Zeitaufwand ist in Ihrem code.
Vielleicht teilen Sie den code mit Organisationseinheiten konnten wir vor Ort einige große Ineffizienz.
Edit:
Ich weiß nicht, wie Sie Ihren Algorithmus. Sucht-und zurück kann schwierig sein, auf dem stream vor allem die Zahl liegt über einen Puffer-Grenze. Ich würde nur eine Nummer jedes mal durch die Schleife.
Versuchen Sie dies:
Hinweis: Dies ist nicht optimal (und es wird davon ausgegangen stream-Eingabe von zahlen (während Ihr sieht Binär -)) Aber ich bin sicher, Sie können es verwenden, wie ein Ausgangspunkt.
fstream
(einschließlich gcc und Visual C++'s) sind bekannt für die schlechte performance.ofstream.write
(4 bytes) an einen benutzerdefinierten Puffer undWriteFile
und sah ein 10x Verbesserung. Gibt es ähnliche Ineffizienzen auf Lesen, obwohl ich zugeben muss, dass nachdem ich das problem mitofstream.write
, änderte ich den Las-code direkt auf OS-vorausgesetzt, bedeutet, dass ohne eine einstweiligeifstream.read
version.