149 votes

L'utilisation de scanf() dans les programmes C++ est plus rapide que l'utilisation de cin ?

Je ne sais pas si c'est vrai, mais en lisant la FAQ d'un des sites fournissant des informations sur les problèmes, j'ai trouvé quelque chose qui a attiré mon attention :

Vérifiez vos méthodes d'entrée/sortie. En C++, l'utilisation de cin et cout est trop lente. En les utilisant, vous vous garantissez de ne pouvoir résoudre aucun problème avec une quantité décente d'entrée ou de sortie. Utilisez plutôt printf et scanf.

Quelqu'un peut-il clarifier ce point ? Est-ce que l'on utilise vraiment scanf() dans les programmes C++ plus rapidement qu'en utilisant cin >> quelque chose ? Si oui, est-ce une bonne pratique de l'utiliser dans les programmes C++ ? Je pensais que c'était spécifique au C, bien que je sois en train d'apprendre le C++...

0 votes

Je suis curieux de savoir quel genre de problèmes ils ont pour lesquels ils pensent que ce sera un problème. Vous avez un lien vers ce site ?

0 votes

@Eclipse : voici le lien vers le site : spoj.pl La citation ci-dessus a été trouvée quelque part sur les forums.

17 votes

A mon avis, un mauvais programmeur accuse les bibliothèques standard d'être responsables des mauvaises performances. Un peu comme le cri toujours humoristique "Je pense avoir trouvé un bug dans GCC".

242voto

nibot Points 5057

Voici un test rapide d'un cas simple : un programme qui lit une liste de nombres à partir de l'entrée standard et effectue un XOR de tous les nombres.

version iostream :

#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;
}

version scanf :

#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;
}

Résultats

En utilisant un troisième programme, j'ai généré un fichier texte contenant 33 280 276 nombres aléatoires. Les temps d'exécution sont :

iostream version:  24.3 seconds
scanf version:      6.4 seconds

La modification des paramètres d'optimisation du compilateur n'a pas semblé modifier les résultats de façon significative.

Donc : il y a vraiment une différence de vitesse.


EDITAR: Utilisateur clyfish souligne ci-dessous que la différence de vitesse est largement due au fait que les fonctions d'E/S d'iostream maintiennent la synchronisation avec les fonctions d'E/S du C. Nous pouvons désactiver cette synchronisation par un appel à std::ios::sync_with_stdio(false); :

#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;
}

Nouveaux résultats :

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

C++ iostream gagne ! Il s'avère que cette synchronisation/balayage interne est ce qui ralentit normalement les entrées/sorties de iostream. Si nous ne mélangeons pas stdio et iostream, nous pouvons le désactiver, et iostream est alors plus rapide.

Le code : https://gist.github.com/3845568

8 votes

Je pense que l'utilisation de 'endl' peut ralentir l'exécution.

5 votes

L'utilisation de std::endl n'est pas dans la boucle.

0 votes

Ça ne fait aucune différence avec la synchronisation activée ou désactivée. C'est la faute de libc++. Ca ne fait que booster libstdc++

86voto

clyfish Points 3128

http://www.quora.com/Is-cin-cout-slower-than-scanf-printf/answer/Aditya-Vishwakarma

Performance de cin / cout peuvent être lents car ils doivent se synchroniser avec la bibliothèque C sous-jacente. Ceci est essentiel si l'on souhaite utiliser à la fois C IO et C++ IO.

Toutefois, si vous n'utilisez que l'entrée/sortie C++, il suffit d'utiliser la ligne ci-dessous avant toute opération d'entrée/sortie.

std::ios::sync_with_stdio(false);

Pour plus d'informations à ce sujet, consultez la page correspondante. Documentation sur libstdc++ .

0 votes

Je viens de vérifier la ligne ci-dessus (std::ios::sync_with_stdio(false) ;) Et cela rend iostream presque aussi rapide que cstdio.

0 votes

Utiliser également cin.tie(static_cast<ostream*>(0)) ; pour de meilleures performances

42voto

1800 INFORMATION Points 55907

Il est probable que scanf soit un peu plus rapide que l'utilisation de streams. Bien que les flux offrent une grande sécurité de type et ne doivent pas analyser les chaînes de format au moment de l'exécution, ils ont généralement l'avantage de ne pas nécessiter d'allocations de mémoire excessives (cela dépend de votre compilateur et de votre système d'exécution). Cela dit, à moins que la performance ne soit votre seul objectif final et que vous soyez sur le chemin critique, vous devriez vraiment privilégier les méthodes plus sûres (plus lentes).

Il y a un article très délicieux écrit ici par Herb Sutter " Les formateurs de cordes de Manor Farm "qui explique en détail les performances des formateurs de chaînes de caractères tels que sscanf y lexical_cast et quelles sortes de choses les faisaient fonctionner lentement ou rapidement. C'est un peu analogue, probablement au genre de choses qui affectent les performances entre les IO de style C et celles de style C++. La principale différence avec les formateurs était la sécurité des types et le nombre d'allocations de mémoire.

21voto

Bogatyr Points 12027

Je viens de passer une soirée à travailler sur un problème sur UVa Online (Factovisors, un problème très intéressant, consultez-le) :

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=35&page=show_problem&problem=1080

J'obtenais des TLE (limite de temps dépassée) sur mes soumissions. Sur ces sites de résolution de problèmes en ligne, vous disposez d'une limite de temps de 2 à 3 secondes pour gérer les milliers de cas de test utilisés pour évaluer votre solution. Pour les problèmes à forte intensité de calcul comme celui-ci, chaque microseconde compte.

J'utilisais l'algorithme suggéré (lu dans les forums de discussion du site), mais j'obtenais toujours des TLE.

J'ai changé juste "cin >> n >> m" en "scanf( "%d %d", &n, &m )" et les quelques petits "couts" en "printfs", et mon TLE est devenu "Accepté" !

Donc, oui, cela peut faire une grande différence, surtout lorsque les délais sont courts.

1 votes

Accepter. La même chose m'est arrivée à l'UVA. Problème de juge en ligne : les copains de l'armée. uva.onlinejudge.org/

10voto

John Kugelman Points 108754

Wow, tu parles d'une optimisation prématurée. Si ce n'est pas une optimisation ridicule. L'E/S va bloquer votre programme bien avant que cin >> x maximise votre CPU quadcore.

OK, la méchanceté mise à part : Non, ce n'est pas une bonne pratique d'échanger <iostream> para <cstdio> . En C++, utilisez les bibliothèques C++. N'utilisez pas scanf Ne pas appeler malloc ne pas passer, ne pas collecter 200 $.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X