Pourquoi C++ lit les lignes de stdin plus lentement que Python ? Analyse et solution

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Introduction : Le paradoxe de la vitesse qui a explosé Stack Overflow

\n\n

Imaginez la situation : vous résolvez un problème de compétition ou traitez un fichier journal d'un gigaoctet. Le script Python s'exécute en 2 secondes. Vous le réécrivez en C++, en espérant une accélération décuplée, mais… vous obtenez 10 secondes ! Une douleur familière ? C'est exactement cette question qui a recueilli des milliers de vues sur Stack Overflow et a donné naissance à une discussion légendaire : « Why is reading lines from stdin much slower in C++ than Python? ».

\n\n

Comment se fait-il que le C++ « rapide » puisse perdre face au Python « lent » dans une opération aussi triviale que la lecture de lignes ? La réponse ne réside pas dans la vitesse du langage lui-même, mais dans les paramètres par défaut et l'architecture de iostream. Dans cet article, nous allons mener notre propre enquête, écrire du code de test en C++ et Python, mesurer le temps et, surtout, apprendre à rendre les entrées-sorties en C++ vraiment rapides.

\n\n

Cet article n'est pas une théorie aride, mais un guide pratique pour tous ceux qui écrivent en C++ et rencontrent des problèmes de performance des entrées-sorties. C'est parti !

\n\n

Le cœur du problème : Pourquoi iostream « ralentit-il » ?

\n\n

Lorsque vous écrivez std::cin >> data ou std::getline(std::cin, line), C++ fait par défaut quelque chose dont beaucoup ne se doutent même pas. Il synchronise ses flux d'entrée-sortie avec les flux standard de C (stdin, stdout). Pourquoi ? Pour la compatibilité : vous pouvez utiliser simultanément printf et std::cout dans un même programme, et la sortie ne sera pas mélangée.

\n\n

Cette synchronisation coûte cher. Chaque appel à cin ou cout vérifie l'état des flux C, transformant une opération tamponnée rapide en une opération synchrone lente.

\n\n

En Python, c'est tout différent. La fonction input() et sys.stdin.readline() utilisent leur propre tampon, bien optimisé, au niveau du C. Pas de synchronisation superflue — juste la lecture d'un bloc de données depuis le descripteur de fichier. C'est pourquoi la lecture depuis stdin en Python peut être plus rapide qu'en C++ « prêt à l'emploi ».

\n\n

Expérience : Test de vitesse

\n\n

Vérifions cela en pratique. Écrivons un programme simple qui lit 1 000 000 de lignes depuis stdin et ne fait rien avec (seulement les lire). D'abord en C++ « tel quel » :

\n\n
// slow_cin.cpp\n#include <iostream>\n#include <string>\n\nint main() {\n    std::ios::sync_with_stdio(false); // Commentons pour l'instant\n    std::cin.tie(nullptr);           // Et ceci\n\n    std::string line;\n    while (std::getline(std::cin, line)) {\n        // Ne rien faire\n    }\n    return 0;\n}
\n\n

Et maintenant en Python :

\n\n
# fast_python.py\nimport sys\n\ndef main():\n    for line in sys.stdin:\n        pass\n\nif __name__ == "__main__":\n    main()
\n\n

Lançons le test avec seq 1000000 | ./slow_cin et seq 1000000 | python3 fast_python.py. Le résultat sera choquant : le C++ sans optimisations peut être 5 à 10 fois plus lent que Python ! Mais ne vous précipitez pas pour enterrer le C++ — le problème se résout avec deux lignes de code.

\n\n

Solution : Deux lignes magiques

\n\n

Tout ce dont vous avez besoin pour accélérer les entrées-sorties en C++ est de désactiver la synchronisation et la liaison des flux. Ajoutez au début de main() :

\n\n
std::ios::sync_with_stdio(false);\nstd::cin.tie(nullptr);
\n\n

La première ligne désactive la synchronisation entre iostream et stdio. La seconde détache cin de cout (par défaut, avant chaque opération d'entrée, cout vide son tampon, ce qui ralentit également le travail). Après cela, votre code C++ commencera à fonctionner au même niveau que Python, et souvent plus rapidement.

\n\n

Vérifions le résultat

\n\n

Maintenant, décommentez ces lignes dans notre test et relancez-le. Vous verrez que la performance du C++ décolle. Dans certains benchmarks, la différence atteint 10 fois.

Blogs

Book Recommendations