C ++ ifstream :: lies langsam wegen memcpy

8

Kürzlich habe ich beschlossen, einige Dateilesevorgänge zu optimieren, die ich gemacht habe, denn wie jeder sagt, ist es viel schneller, einen großen Datenblock in einen Puffer zu lesen und dann mit ihm zu arbeiten, als viele kleine Lesevorgänge zu verwenden. Und mein Code ist jetzt sicherlich viel schneller, aber nach einigen Profilergebnissen scheint es, dass Memcpy viel Zeit in Anspruch nimmt.

Der Kern meines Codes ist ...

%Vor%

Ich benutze Visual Studio 11 und nachdem ich meinen Code profiliert habe, heißt es ifstream::read() ruft schließlich xsgetn() auf, welches vom internen Puffer in meinen Puffer kopiert. Dieser Vorgang beansprucht über 80% der Zeit! An zweiter Stelle folgt uflow() , das 10% der Zeit beansprucht.

Gibt es eine Möglichkeit, das Kopieren zu umgehen? Kann ich dem ifstream irgendwie sagen, dass ich die benötigte Größe direkt in meinen Puffer puffern soll? Verwendet der C-Style FILE* auch einen solchen internen Puffer?

UPDATE: Aufgrund der Leute, die mir sagen, dass ich cstdio benutzen soll ... habe ich einen Benchmark gemacht.

EDIT: Leider war der alte Code voller Fehler (er hat nicht einmal die ganze Datei gelesen!). Sie können es hier sehen: Ссылка

Hier ist mein neuer Maßstab:

%Vor%

Zeiten sind:
185
80
78

Nun ... sieht so aus, als wäre die Verwendung des C-Stils schneller als ifstream :: read. Außerdem bietet die Verwendung von windows ReadFile nur einen kleinen Vorteil, der vernachlässigbar ist (ich habe mir den Code angesehen und fread ist im Grunde ein Wrapper um ReadFile). Sieht so aus, als würde ich schließlich zu fread wechseln.

Mann, es ist verwirrend, einen Benchmark zu schreiben, der diese Dinge tatsächlich richtig testet.

SCHLUSSFOLGERUNG: Die Verwendung von <cstdio> ist schneller als <fstream> . Der Grund dafür, dass fstream langsamer ist, liegt darin, dass C ++ - Streams ihren eigenen internen Puffer haben. Dies führt zu einem zusätzlichen Kopieren, wenn Sie lesen / schreiben, und dieses Kopieren berücksichtigt die gesamte zusätzliche Zeit, die von fstream benötigt wird. Noch schockierender ist, dass die zusätzliche Zeit länger ist als die Zeit, um die Datei tatsächlich zu lesen.

    
retep998 25.04.2012, 22:14
quelle

3 Antworten

3

Wenn Sie Datei-I / O beschleunigen möchten, empfehle ich Ihnen, das gute alte ' <cstdio> ' zu verwenden, da es das C ++ - Programm mit großem Abstand übertreffen kann.

    
orlp 25.04.2012, 22:19
quelle
5
  

Kann ich dem ifstream irgendwie sagen, dass er die benötigte Größe direkt puffern soll?   in meinen Puffer?

Ja, das ist pubsetbuf () für.

Aber wenn Sie sich Gedanken darüber machen wollen, wie Sie eine Datei lesen, sollten Sie auch die Speicherzuordnung in Betracht ziehen. boost hat eine portable Implementierung .

    
Cubbi 25.04.2012 22:19
quelle
1

Es wurde mehrfach bewiesen, dass Daten auf Linux-Systemen am schnellsten gelesen werden können. Ich weiß nichts über Windows. Allerdings wird es ohne diese Pufferung sicher gehen.

mmap() , fopen() , fread() ( fwrite() ) ist etwas höherwertig und kann einen Puffer induzieren, während FILE* , open() , read() Funktionen niedrige Werte und der einzige Puffer sind Sie können dort aus dem Os Kernel kommen.

    
ypnos 25.04.2012 22:21
quelle