Ich weiß nicht, ob dies der Fall ist, aber als ich FAQ auf einer der Problembereitstellungsseiten las, fand ich etwas, das meine Aufmerksamkeit auf sich zog:
Überprüfen Sie Ihre Eingabe- / Ausgabemethoden. In C ++ ist die Verwendung von cin und cout zu langsam. Verwenden Sie diese, und Sie werden garantiert kein Problem mit einer angemessenen Menge an Eingabe oder Ausgabe lösen können. Verwenden Sie stattdessen printf und scanf.
Kann das bitte jemand klären? Ist die Verwendung von scanf () in C ++ - Programmen wirklich schneller als die Verwendung von cin >> ? Wenn ja, ist es eine gute Praxis, es in C ++ - Programmen zu verwenden? Ich dachte, dass es C-spezifisch ist, obwohl ich gerade C ++ lerne ...
c++
c
performance
io
zeroDivisible
quelle
quelle
Antworten:
Hier ist ein kurzer Test eines einfachen Falls: Ein Programm zum Lesen einer Liste von Zahlen aus der Standardeingabe und XOR aller Zahlen.
iostream-Version:
scanf version:
Ergebnisse
Mit einem dritten Programm habe ich eine Textdatei mit 33.280.276 Zufallszahlen erstellt. Die Ausführungszeiten sind:
Das Ändern der Optimierungseinstellungen des Compilers schien die Ergebnisse überhaupt nicht zu ändern.
Also: Es gibt wirklich einen Geschwindigkeitsunterschied.
BEARBEITEN : User Clyfish weist unten darauf hin, dass der Geschwindigkeitsunterschied hauptsächlich auf die Iostream-E / A-Funktionen zurückzuführen ist, die die Synchronisation mit den CI / O-Funktionen aufrechterhalten. Wir können dies mit einem Anruf ausschalten
std::ios::sync_with_stdio(false);
:Neue Ergebnisse:
C ++ iostream gewinnt! Es stellt sich heraus, dass diese interne Synchronisierung / Spülung normalerweise die Iostream-E / A verlangsamt. Wenn wir nicht stdio und iostream mischen, können wir es ausschalten, und dann ist iostream am schnellsten.
Der Code: https://gist.github.com/3845568
quelle
iostream
verliert, wenn Sie mehr als eine Ganzzahl in einemscanf
Aufruf analysieren .http://www.quora.com/Is-cin-cout-slower-than-scanf-printf/answer/Aditya-Vishwakarma
Die Leistung von
cin
/cout
kann langsam sein, da sie sich mit der zugrunde liegenden C-Bibliothek synchronisieren müssen. Dies ist wichtig, wenn sowohl C IO als auch C ++ IO verwendet werden sollen.Wenn Sie jedoch nur C ++ - E / A verwenden möchten, verwenden Sie einfach die folgende Zeile, bevor Sie E / A-Vorgänge ausführen.
Weitere Informationen hierzu finden Sie in den entsprechenden libstdc ++ - Dokumenten .
quelle
Wahrscheinlich ist scanf etwas schneller als die Verwendung von Streams. Obwohl Streams viel Typensicherheit bieten und zur Laufzeit keine Formatzeichenfolgen analysieren müssen, hat dies normalerweise den Vorteil, dass keine übermäßigen Speicherzuweisungen erforderlich sind (dies hängt von Ihrem Compiler und Ihrer Laufzeit ab). Das heißt, wenn Leistung nicht Ihr einziges Endziel ist und Sie sich auf dem kritischen Pfad befinden, sollten Sie die sichereren (langsameren) Methoden wirklich bevorzugen.
Es ist ein sehr wohlschmeckender Artikel geschrieben hier von Herb Sutter „ Die String Formatter von Manor Farm “ , die in vielen Details der Leistung des String Formatierer gehen wie
sscanf
undlexical_cast
und was für Dinge machte sie laufen langsam oder schnell. Dies ist eine Art Analogie, wahrscheinlich zu den Dingen, die die Leistung zwischen IO im C-Stil und C ++ - Stil beeinträchtigen würden. Der Hauptunterschied zu den Formatierern bestand in der Typensicherheit und der Anzahl der Speicherzuordnungen.quelle
Ich habe gerade einen Abend damit verbracht, an einem Problem bei UVa Online zu arbeiten (Factovisors, ein sehr interessantes Problem, probieren Sie es aus):
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=35&page=show_problem&problem=1080
Ich habe TLE (Zeitlimit überschritten) für meine Einsendungen erhalten. Auf diesen Online-Richterseiten zur Problemlösung haben Sie ein Zeitlimit von 2-3 Sekunden, um potenziell Tausende von Testfällen zu bearbeiten, die zur Bewertung Ihrer Lösung verwendet werden. Bei rechenintensiven Problemen wie diesem zählt jede Mikrosekunde.
Ich habe den vorgeschlagenen Algorithmus verwendet (siehe in den Diskussionsforen für die Site), bekam aber immer noch TLEs.
Ich habe nur "cin >> n >> m" in "scanf ("% d% d ", & n, & m)" und die wenigen winzigen "couts" in "printfs" geändert, und mein TLE wurde zu "Accepted"!
Ja, es kann einen großen Unterschied machen, insbesondere wenn die Fristen kurz sind.
quelle
Wenn Sie sich sowohl für die Leistung als auch für die Formatierung von Zeichenfolgen interessieren, schauen Sie sich die FastFormat- Bibliothek von Matthew Wilson an .
edit - Link zur Accu-Veröffentlichung in dieser Bibliothek: http://accu.org/index.php/journals/1539
quelle
Es gibt stdio-Implementierungen ( libio ), die FILE * als C ++ - Streambuf und fprintf als Parser im Laufzeitformat implementieren. IOstreams müssen nicht im Laufzeitformat analysiert werden. Dies geschieht alles zur Kompilierungszeit. Wenn die Backends gemeinsam genutzt werden, ist zu erwarten, dass iostreams zur Laufzeit schneller ist.
quelle
Ja, iostream ist langsamer als cstdio.
Ja, Sie sollten cstdio wahrscheinlich nicht verwenden, wenn Sie in C ++ entwickeln.
Allerdings gibt es noch schnellere Möglichkeiten, E / A zu erhalten als scanf, wenn Sie sich nicht für Formatierung, Typensicherheit, bla, bla, bla ... interessieren.
Dies ist beispielsweise eine benutzerdefinierte Routine, um eine Nummer von STDIN abzurufen:
quelle
Das Problem ist, dass
cin
viel Overhead erforderlich ist, da Sie über Abständen eine Abstraktionsschicht erhaltenscanf()
. Sie sollten nichtscanf()
over verwenden,cin
wenn Sie C ++ - Software schreiben, da dies gewünschtcin
ist. Wenn Sie Leistung wünschen, würden Sie wahrscheinlich sowieso keine E / A in C ++ schreiben.quelle
cin
wirklich "abstrakter" (zur Laufzeit) alsscanf
? Ich denke nicht ...scanf
muss die Formatzeichenfolge zur Laufzeit interpretieren, während deriostream
das Format zur Kompilierungszeit kennt.std::istream
konfiguriert wird (über E / A-Manipulatoren oder durch Setzen von Flags für dasistream
Objekt selbst). EinFILE*
Objekt hingegen hat keinen solchen Zustand, so dass ein Aufrufscanf
in dieser Hinsicht viel stabiler ist.Die Anweisungen
cin
und diecout
allgemeine Verwendung scheinen langsamer alsscanf
undprintf
in C ++ zu sein, aber tatsächlich sind sie SCHNELLER!Die Sache ist die : In C ++, wenn Sie verwenden
cin
undcout
ein Synchronisationsvorgang erfolgt standardmäßig, der sicherstellt , dass , wenn Sie beide verwendenscanf
undcin
in Ihrem Programm, dann werden sie beide arbeiten synchron miteinander. Dieser Synchronisierungsvorgang benötigt Zeit. Dahercin
undcout
scheinen langsamer zu sein.Wenn der Synchronisierungsprozess jedoch so eingestellt ist, dass er nicht stattfindet,
cin
ist er schneller alsscanf
.Um den Synchronisierungsvorgang zu überspringen, fügen Sie gleich zu Beginn des folgenden Codeausschnitts in Ihr Programm ein
main()
:Besuchen Sie diese Website für weitere Informationen.
quelle
Es gibt einen Fehler am Ende der Datei, aber dieser C-Code ist dramatisch schneller als die schnellere C ++ - Version.
Das ursprüngliche C ++ dauerte 30 Sekunden, der C-Code 2 Sekunden.
quelle
Natürlich ist es lächerlich, cstdio über iostream zu verwenden. Zumindest wenn Sie Software entwickeln (wenn Sie bereits C ++ über C verwenden, gehen Sie den ganzen Weg und nutzen Sie die Vorteile, anstatt nur unter den Nachteilen zu leiden).
Aber in der Online-Jury, in der Sie keine Software entwickeln, erstellen Sie ein Programm, das in der Lage sein sollte, Dinge zu tun, die Microsoft-Software in 3 Sekunden in 60 Sekunden erreichen muss !!!
In diesem Fall lautet die goldene Regel also (natürlich, wenn Sie mit Java nicht noch mehr Probleme bekommen).
quelle
Selbst wenn
scanf
es schneller wäre alscin
, wäre es egal. Die meiste Zeit lesen Sie von der Festplatte oder der Tastatur. Das Einfügen der Rohdaten in Ihre Anwendung dauert um Größenordnungen länger als das Verarbeitenscanf
odercin
Verarbeiten.quelle
iostream
es langsamer als HDD ist. Ja, es ist so scheiße.