it-swarm.com.de

Die Verwendung von scanf () in C ++ - Programmen ist schneller als die Verwendung von cin?

Ich weiß nicht, ob dies zutrifft, aber als ich FAQ auf einer der Problem-Websites gelesen habe, habe ich etwas gefunden, das meine Aufmerksamkeit erregt hat:

Überprüfen Sie Ihre Eingabe-/Ausgabemethoden. In C++ ist die Verwendung von cin und cout zu langsam. Verwenden Sie diese und Sie werden garantiert nicht in der Lage sein, ein Problem mit einer angemessenen Menge an Input oder Output zu lösen. 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 >> irgendetwas? Wenn ja, ist es eine gute Praxis, es in C++ - Programmen zu verwenden? Ich dachte, es sei C-spezifisch, obwohl ich gerade C++ lerne ...

109
zeroDivisible

Hier ist ein kurzer Test eines einfachen Falls: Ein Programm zum Lesen einer Liste von Zahlen aus der Standardeingabe und XOR alle Zahlen.

iostream-Version:

#include <iostream>

int main(int argc, char **argv) {

  int parity = 0;
  int x;

  while (std::cin >> x)
    parity ^= x;
  std::cout << parity << std::endl;

  return 0;
}

scanf version:

#include <stdio.h>

int main(int argc, char **argv) {

  int parity = 0;
  int x;

  while (1 == scanf("%d", &x))
    parity ^= x;
  printf("%d\n", parity);

  return 0;
}

Ergebnisse

Mit einem dritten Programm habe ich eine Textdatei mit 33.280.276 Zufallszahlen generiert. Die Ausführungszeiten sind:

iostream version:  24.3 seconds
scanf version:      6.4 seconds

Das Ändern der Optimierungseinstellungen des Compilers schien die Ergebnisse überhaupt nicht wesentlich zu verändern.

Also: Es gibt wirklich einen Geschwindigkeitsunterschied.


EDIT: User Clyfish siehe unten dass der Geschwindigkeitsunterschied hauptsächlich auf die Iostream-I/O-Funktionen zurückzuführen ist, die die Synchronisation mit den C I/O-Funktionen aufrechterhalten. Wir können dies mit einem Aufruf von std::ios::sync_with_stdio(false); ausschalten:

#include <iostream>

int main(int argc, char **argv) {

  int parity = 0;
  int x;

  std::ios::sync_with_stdio(false);

  while (std::cin >> x)
    parity ^= x;
  std::cout << parity << std::endl;

  return 0;
}

Neue Ergebnisse:

iostream version:                       21.9 seconds
scanf version:                           6.8 seconds
iostream with sync_with_stdio(false):    5.5 seconds

C++ iostream gewinnt! Es stellt sich heraus, dass diese interne Synchronisierung/Spülung normalerweise iostream i/o 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

197
nibot

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 soll.

Wenn Sie jedoch nur C++ IO verwenden möchten, verwenden Sie einfach die folgende Zeile, bevor Sie IO Operationen ausführen.

std::ios::sync_with_stdio(false);

Weitere Informationen hierzu finden Sie in den entsprechenden libstdc ++ docs .

61
clyfish

Wahrscheinlich ist scanf etwas schneller als 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 der Laufzeit ab). Das heißt, wenn die Leistung nicht Ihr einziges Endziel ist und Sie sich auf dem kritischen Pfad befinden, sollten Sie die sichereren (langsameren) Methoden wirklich bevorzugen.

Es gibt einen sehr leckeren Artikel von Herb Sutter " Die String-Formatierer von Manor Farm ", der ausführlich auf die Leistung von String-Formatierern wie sscanf und lexical_cast Und welche Art von Dingen ließen sie langsam oder schnell laufen. Dies ist eine Art Analogie, wahrscheinlich zu den Dingen, die die Leistung zwischen C-Stil IO und C++ - Stil beeinflussen würden. Der Hauptunterschied zu den Formatierern bestand in der Art der Sicherheit und der Anzahl der Speicher Zuweisungen.

42

Wenn Sie sich sowohl für die Leistung als auch für die Formatierung von Zeichenfolgen interessieren, schauen Sie sich die Bibliothek Matthew Wilsons FastFormat an.

bearbeiten - Link zur Accu-Veröffentlichung in dieser Bibliothek: http://accu.org/index.php/journals/1539

6
xtofl

Ja, iostream ist langsamer als cstdio.
Ja, Sie sollten cstdio wahrscheinlich nicht verwenden, wenn Sie in C++ entwickeln.
Abgesehen davon gibt es noch schnellere Möglichkeiten, E/A zu erhalten als das Scannen, wenn Sie sich nicht um Formatierung, Typensicherheit, bla, bla, bla ... kümmern.

Zum Beispiel ist dies eine benutzerdefinierte Routine, um eine Nummer von STDIN zu erhalten:

inline int get_number()
{
    int c;        
    int n = 0;

    while ((c = getchar_unlocked()) >= '0' && c <= '9')
    {
        // n = 10 * n + (c - '0');
        n = (n << 3) + ( n << 1 ) + c - '0';
    }
    return n;
}
2
pedro.lupin

Es gibt stdio-Implementierungen ( libio ), die FILE * als C++ - Streambuf und fprintf als Laufzeitformat-Parser implementieren. Für IOstreams ist kein Parsing des Laufzeitformats erforderlich. Dies erfolgt zum Zeitpunkt der Kompilierung. Da die Backends gemeinsam genutzt werden, ist zu erwarten, dass iostreams zur Laufzeit schneller sind.

2
MSalters

Das Problem ist, dass cin viel Overhead verursacht, da Sie eine Abstraktionsebene über scanf() -Aufrufen erhalten. Sie sollten scanf() nicht über cin verwenden, wenn Sie C++ - Software schreiben, weil dies cin ist. Wenn Sie Leistung wünschen, würden Sie wahrscheinlich ohnehin keine E/A in C++ schreiben.

1
dreamlax

Die Anweisungen cin und cout scheinen im Allgemeinen langsamer zu sein als scanf und printf in C++, aber tatsächlich sind sie SCHNELLER!

Die Sache ist: Wenn Sie in C++ cin und cout verwenden, wird standardmäßig ein Synchronisationsprozess ausgeführt, der sicherstellt, dass Sie sowohl scanf als auch cin verwenden ] _ in Ihrem Programm, dann arbeiten beide synchron miteinander. Dieser Synchronisierungsvorgang benötigt Zeit. Daher scheinen cin und cout langsamer zu sein.

Wenn jedoch festgelegt ist, dass der Synchronisierungsprozess nicht stattfindet, ist cin schneller als scanf.

Um den Synchronisierungsvorgang zu überspringen, fügen Sie den folgenden Codeausschnitt direkt am Anfang von main() in Ihr Programm ein:

std::ios::sync_with_stdio(false);

Besuchen Sie diese Seite für weitere Informationen.

0
#include <stdio.h>
#include <unistd.h>

#define likely(x)       __builtin_expect(!!(x), 1)
#define unlikely(x)     __builtin_expect(!!(x), 0)

static int scanuint(unsigned int* x)
{
  char c;
  *x = 0;

  do
  {
      c = getchar_unlocked();
      if (unlikely(c==EOF)) return 1;
  } while(c<'0' || c>'9');

  do
  {
      //*x = (*x<<3)+(*x<<1) + c - '0';
      *x = 10 * (*x) + c - '0';
      c = getchar_unlocked();
      if (unlikely(c==EOF)) return 1;
  } while ((c>='0' && c<='9'));

  return 0;
}

int main(int argc, char **argv) {

  int parity = 0;
  unsigned int x;

  while (1 != (scanuint(&x))) {
    parity ^= x;
  }
  parity ^=x;
  printf("%d\n", parity);

  return 0;
}

Es gibt einen Fehler am Ende der Datei, aber dieser C-Code ist erheblich schneller als die schnellere C++ - Version.

[email protected] 3845568-78602a3f95902f3f3ac63b6beecaa9719e28a6d6 ▶ make test        
time ./xor-c < Rand.txt
360589110

real    0m11,336s
user    0m11,157s
sys 0m0,179s
time ./xor2-c < Rand.txt
360589110

real    0m2,104s
user    0m1,959s
sys 0m0,144s
time ./xor-cpp < Rand.txt
360589110

real    0m29,948s
user    0m29,809s
sys 0m0,140s
time ./xor-cpp-noflush < Rand.txt
360589110

real    0m7,604s
user    0m7,480s
sys 0m0,123s

Das ursprüngliche C++ dauerte 30 Sekunden, der C-Code 2 Sekunden.

0
hexec