Sehr überraschende Perfs von fprintf vs std :: ofstream (fprintf ist sehr langsam)

7

Ich habe einige Benchmarks ausgeführt, um die effizienteste Möglichkeit zu finden, ein riesiges Array in eine Datei in C ++ zu schreiben (mehr als 1Go in ASCII).

Also habe ich std :: ofstream mit fprintf verglichen (siehe den Schalter, den ich unten benutzt habe)

%Vor%

Und mein großes Problem ist, dass fprintf im Vergleich zu std :: ofstream um 12x langsamer zu sein scheint. Haben Sie eine Vorstellung davon, woher das Problem in meinem Code stammt? Oder vielleicht ist std :: ofstream im Vergleich zu fprintf sehr optimiert?

(und eine andere Frage: Kennen Sie einen anderen schnelleren Weg, um eine Datei zu schreiben)

Vielen Dank

(Detail: Ich habe mit g ++ -Wall -O3 kompiliert)

    
Vincent 24.10.2011, 14:53
quelle

5 Antworten

16

fprintf("%d" erfordert eine Laufzeitanalyse der Formatzeichenfolge, einmal pro Integer. ostream& operator<<(ostream&, int) wird vom Compiler einmal pro Kompilierung aufgelöst.

    
MSalters 24.10.2011, 14:59
quelle
4

Nun, fprintf() muss zur Laufzeit etwas mehr arbeiten, da es die Formatzeichenfolge parsen und verarbeiten muss. Angesichts der Größe Ihrer Ausgabedatei würde ich jedoch erwarten, dass diese Unterschiede von geringer Bedeutung sind, und würde erwarten, dass der Code E / A-gebunden ist.

Ich vermute daher, dass Ihr Benchmark in gewisser Weise fehlerhaft ist.

  1. Erhalten Sie regelmäßig 12x Unterschied, wenn Sie die Tests wiederholt ausführen?
  2. Was passiert mit den Zeitvorgaben, wenn Sie die Reihenfolge ändern, in der Sie die Tests ausführen?
  3. Was passiert, wenn Sie fsync()/sync() am Ende aufrufen?
NPE 24.10.2011 15:02
quelle
2

Es gibt einen Dateipuffer im Ofstream, dies kann den Zugriff auf den Datenträger verringern. Außerdem ist fprintf eine Funktion mit variablen Parametern, die einige va_ # -Funktionen aufrufen, aber ofstream nicht. Ich denke, Sie können fwrite () oder putc () verwenden, um einen Test zu haben.

    
YangG 24.10.2011 15:30
quelle
1

Haben Sie sync_with_stdio irgendwo vor dem Code, den Sie angezeigt haben, gesetzt?

Während das, was Sie berichten, dem empirisch gesehen entgegengesetzt ist, denken und glauben die meisten Menschen, was Sie sehen, sollte die Norm sein. Iostreams sind typsicher, während die printf-Familie von Funktionen variable Funktionen sind, die aus dem Formatspezifizierer auf die Typen der va_list schließen müssen.

    
Happy Green Kid Naps 24.10.2011 15:00
quelle
1

Ich präsentiere hier eine wirklich optimierte Möglichkeit, ganze Zahlen in Textdateien zu schreiben, indem ich Unix-Funktionen öffne, lese und schreibe. Sie sind auch auf Windows verfügbar, geben Sie nur eine Warnung, mit der Sie arbeiten können. Diese Implementierung funktioniert nur für 32-Bit-Integer.

In Ihrer Include-Datei:

%Vor%

In Ihrer Quelldatei

%Vor%

Ich denke, das wird jede andere Methode übertreffen, um in eine ASCII-Datei zu schreiben :) Sie können etwas mehr Leistung mit Windows Low-Level-API WriteFile und ReadFile bekommen, aber es lohnt sich nicht.

Um es zu benutzen ...

%Vor%

Wenn Sie keine Datei angeben, wird die Standardausgabe (Konsole) verwendet.

    
Salvatore Previti 24.10.2011 15:50
quelle

Tags und Links