Ich wollte das Lesen von Zeilen der Zeichenfolgeneingabe von stdin mit Python und C ++ vergleichen und war schockiert, als mein C ++ - Code eine Größenordnung langsamer als der entsprechende Python-Code ausgeführt wurde. Da mein C ++ rostig ist und ich noch kein Pythonista-Experte bin, sagen Sie mir bitte, ob ich etwas falsch mache oder ob ich etwas falsch verstehe.
(TLDR-Antwort: Fügen Sie die Anweisung hinzu: cin.sync_with_stdio(false)
oder verwenden Sie fgets
stattdessen einfach .
TLDR-Ergebnisse: Scrollen Sie bis zum Ende meiner Frage und sehen Sie sich die Tabelle an.)
C ++ - Code:
#include <iostream>
#include <time.h>
using namespace std;
int main() {
string input_line;
long line_count = 0;
time_t start = time(NULL);
int sec;
int lps;
while (cin) {
getline(cin, input_line);
if (!cin.eof())
line_count++;
};
sec = (int) time(NULL) - start;
cerr << "Read " << line_count << " lines in " << sec << " seconds.";
if (sec > 0) {
lps = line_count / sec;
cerr << " LPS: " << lps << endl;
} else
cerr << endl;
return 0;
}
// Compiled with:
// g++ -O3 -o readline_test_cpp foo.cpp
Python-Äquivalent:
#!/usr/bin/env python
import time
import sys
count = 0
start = time.time()
for line in sys.stdin:
count += 1
delta_sec = int(time.time() - start_time)
if delta_sec >= 0:
lines_per_sec = int(round(count/delta_sec))
print("Read {0} lines in {1} seconds. LPS: {2}".format(count, delta_sec,
lines_per_sec))
Hier sind meine Ergebnisse:
$ cat test_lines | ./readline_test_cpp
Read 5570000 lines in 9 seconds. LPS: 618889
$cat test_lines | ./readline_test.py
Read 5570000 lines in 1 seconds. LPS: 5570000
Ich sollte beachten, dass ich dies sowohl unter Mac OS X 10.6.8 (Snow Leopard) als auch unter Linux 2.6.32 (Red Hat Linux 6.2) versucht habe. Ersteres ist ein MacBook Pro, und letzteres ist ein sehr leistungsfähiger Server, nicht dass dies zu relevant wäre.
$ for i in {1..5}; do echo "Test run $i at `date`"; echo -n "CPP:"; cat test_lines | ./readline_test_cpp ; echo -n "Python:"; cat test_lines | ./readline_test.py ; done
Test run 1 at Mon Feb 20 21:29:28 EST 2012
CPP: Read 5570001 lines in 9 seconds. LPS: 618889
Python:Read 5570000 lines in 1 seconds. LPS: 5570000
Test run 2 at Mon Feb 20 21:29:39 EST 2012
CPP: Read 5570001 lines in 9 seconds. LPS: 618889
Python:Read 5570000 lines in 1 seconds. LPS: 5570000
Test run 3 at Mon Feb 20 21:29:50 EST 2012
CPP: Read 5570001 lines in 9 seconds. LPS: 618889
Python:Read 5570000 lines in 1 seconds. LPS: 5570000
Test run 4 at Mon Feb 20 21:30:01 EST 2012
CPP: Read 5570001 lines in 9 seconds. LPS: 618889
Python:Read 5570000 lines in 1 seconds. LPS: 5570000
Test run 5 at Mon Feb 20 21:30:11 EST 2012
CPP: Read 5570001 lines in 10 seconds. LPS: 557000
Python:Read 5570000 lines in 1 seconds. LPS: 5570000
Winziger Benchmark-Nachtrag und Zusammenfassung
Der Vollständigkeit halber dachte ich, ich würde die Lesegeschwindigkeit für dieselbe Datei auf derselben Box mit dem ursprünglichen (synchronisierten) C ++ - Code aktualisieren. Dies gilt wiederum für eine 100-MB-Zeilendatei auf einer schnellen Festplatte. Hier ist der Vergleich mit mehreren Lösungen / Ansätzen:
Implementation Lines per second
python (default) 3,571,428
cin (default/naive) 819,672
cin (no sync) 12,500,000
fgets 14,285,714
wc (not fair comparison) 54,644,808
<iostream>
Leistung ist schlecht. Nicht das erste Mal, dass es passiert. 2) Python ist klug genug, um die Daten nicht in die for-Schleife zu kopieren, weil Sie sie nicht verwenden. Sie könnten erneut versuchen, zu verwenden scanf
und a char[]
. Alternativ können Sie versuchen, die Schleife neu zu schreiben, damit etwas mit der Zeichenfolge getan wird (z. B. den 5. Buchstaben behalten und in einem Ergebnis verketten).
cin.eof()
!! Setzen Sie den getline
Aufruf in die 'if'-Anweisung.