Je voulais comparer les lignes de lecture des entrées de chaîne de stdin en utilisant Python et C ++ et j'ai été choqué de voir mon code C ++ s'exécuter un ordre de grandeur plus lentement que le code Python équivalent. Comme mon C ++ est rouillé et que je ne suis pas encore un expert Pythonista, dites-moi si je fais quelque chose de mal ou si je me méprends sur quelque chose.
(Réponse TLDR: incluez la déclaration: cin.sync_with_stdio(false)
ou utilisez simplement à la fgets
place.
Résultats TLDR: faites défiler jusqu'au bas de ma question et regardez le tableau.)
Code C ++:
#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
Équivalent Python:
#!/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))
Voici mes résultats:
$ 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
Je dois noter que j'ai essayé ceci sous Mac OS X v10.6.8 (Snow Leopard) et Linux 2.6.32 (Red Hat Linux 6.2). Le premier est un MacBook Pro, et le second est un serveur très costaud, pas que ce soit trop pertinent.
$ 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
Petit addenda de référence et récapitulation
Pour être complet, j'ai pensé mettre à jour la vitesse de lecture du même fichier sur la même boîte avec le code C ++ d'origine (synchronisé). Encore une fois, c'est pour un fichier de ligne 100M sur un disque rapide. Voici la comparaison, avec plusieurs solutions / approches:
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>
performances sont nulles. Pas la première fois que ça arrive. 2) Python est assez intelligent pour ne pas copier les données dans la boucle for car vous ne les utilisez pas. Vous pouvez retester en essayant d'utiliser scanf
et a char[]
. Alternativement, vous pouvez essayer de réécrire la boucle afin que quelque chose soit fait avec la chaîne (par exemple, gardez la 5ème lettre et concaténez-la en résultat).
cin.eof()
!! Mettez l' getline
appel dans l'instruction «if».