On m'a assigné un exercice dans mon université. Je l'ai ramené chez moi et j'ai essayé de programmer un algorithme pour le résoudre, c'était quelque chose lié aux graphiques, trouver des composants connectés, je suppose.
Ensuite, j'ai fait la chose la plus triviale qui me soit venue à l'esprit et je l'ai ensuite montrée à mon professeur. Après une brève observation, il a perçu que la complexité d'exécution de ma solution était inviable et montrait quelque chose de plus efficace. Et il y a une tradition de programmeurs qui n'ont aucune idée de ce qu'est la complexité de calcul (j'en faisais partie), est-ce donc un problème si un programmeur n'a aucune idée de ce qu'est la complexité de calcul?
algorithms
algorithm-analysis
education
applied-theory
Billy Rubina
la source
la source
Réponses:
Oui, je dirais que connaître quelque chose sur la complexité de calcul est un must pour tout programmeur sérieux. Tant que vous ne traitez pas d'énormes ensembles de données, tout ira bien sans connaître la complexité, mais si vous voulez écrire un programme qui s'attaque à de graves problèmes, vous en avez besoin.
Dans votre cas spécifique, votre exemple de recherche de composants connectés peut avoir fonctionné pour des graphiques de jusqu'à nœuds. Cependant, si vous avez essayé un graphique avec 100000 nœuds, l'algorithme de votre professeur aurait probablement réussi cela en 1 seconde, tandis que votre algorithme aurait (selon la gravité de la complexité) pris 1 heure, 1 jour, ou peut-être même 1 éternité.100 100.000
Une erreur quelque peu courante que les étudiants font dans notre cours d'algorithmes est d'itérer sur un tableau comme celui-ci:
Ce n'est peut-être pas le code le plus beau, mais dans un programme compliqué, quelque chose comme ça peut apparaître sans que le programmeur en soit conscient. Maintenant, quel est le problème avec ce programme?
Supposons que nous l'exécutons sur un ensemble de données de éléments. Par rapport au programme suivant, l'ancien programme fonctionnera 50 000 plus lentement.100.000 50.000
J'espère que vous convenez qu'avoir les connaissances nécessaires pour faire fonctionner votre programme fois plus rapidement est probablement une chose importante pour un programmeur. Comprendre la différence entre les deux programmes nécessite des connaissances de base sur la théorie de la complexité et des connaissances sur les particularités du langage dans lequel vous programmez.50.000
Ce n'est qu'un exemple de jouet, mais cela nécessite déjà une compréhension de base de la complexité pour faire la différence entre les deux programmes, et si vous essayez réellement de déboguer / optimiser un programme plus compliqué qui a cette erreur, il faut une compréhension encore plus grande pour trouver où est le bug. Parce qu'une erreur comme la suppression d'un élément d'un tableau de cette façon peut être très bien cachée par des abstractions dans le code.
Une bonne compréhension de la complexité permet également de comparer deux approches pour résoudre un problème. Supposons que vous ayez trouvé deux approches différentes pour résoudre le problème des composants connectés par vous-même: afin de décider entre eux, il serait très utile d'estimer (rapidement) leur complexité et de choisir la meilleure.
la source
"So long as you are not dealing with huge data sets you will be fine not knowing complexity"
C'est souvent vrai, mais pas toujours. Par exemple, unO(n!)
algorithme ne sera pas viable même pour des ensembles de données relativement petits. Si vous utilisez unO(n!)
algorithme où vous auriez pu utiliserO(n^2)
votre programme, l'exécution prendra 36 288 fois plus longtemps avec une taille de données de 10 . Sur une taille de données de 20, vous regardez 2,4 quintillions d'opérations.Il s'agit d'une réfutation de la réponse de Tom van der Zanden , qui déclare que c'est un must.
La chose est, la plupart du temps, 50 000 fois plus lente n'est pas pertinente (sauf si vous travaillez chez Google bien sûr).
Si l'opération que vous effectuez prend une microseconde ou si votre N n'est jamais au-dessus d'un certain seuil (une grande partie du codage fait de nos jours), cela n'aura JAMAIS d'importance. Dans ces cas, penser à la complexité de calcul ne fera que vous faire perdre du temps (et probablement de l'argent).
La complexité informatique est un outil pour comprendre pourquoi quelque chose peut être lent ou mal évoluer, et comment l'améliorer, mais la plupart du temps, c'est une surpuissance totale.
Je suis programmeur professionnel depuis plus de cinq ans maintenant et je n'ai jamais trouvé la nécessité de penser à la complexité de calcul lors d'une boucle à l'intérieur d'une boucle O (M * N) car toujours l'opération est vraiment rapide ou M et N le sont petit.
Il existe des choses beaucoup plus importantes, généralement utilisées et plus difficiles à comprendre pour quiconque effectue des tâches de programmation (le filetage et le profilage sont de bons exemples dans le domaine des performances).
Bien sûr, il y a certaines choses que vous ne pourrez jamais faire sans comprendre la complexité du calcul (par exemple: trouver des anagrammes sur un dictionnaire), mais la plupart du temps vous n'en avez pas besoin.
la source
Je développe des logiciels depuis une trentaine d'années, travaillant à la fois en tant qu'entrepreneur et employé, et j'ai plutôt bien réussi. Ma première langue était BASIC, mais je me suis vite appris le langage machine pour obtenir une vitesse décente de ma boîte sous-alimentée. J'ai passé beaucoup de temps dans les profileurs au fil des ans et j'ai beaucoup appris sur la production de code optimisé rapide et efficace en mémoire.
Quoi qu'il en soit, je suis autodidacte. Je n'ai jamais rencontré la notation O jusqu'à ce que je commence à interviewer il y a quelques années. Cela ne revient jamais dans mon travail professionnel SAUF lors des entretiens. J'ai donc dû apprendre les bases juste pour gérer cette question lors des entretiens.
Je me sens comme le musicien de jazz qui ne sait pas lire les partitions. Je peux toujours jouer très bien. Je connais les tables de hachage (diable, j'ai inventé les tables de hachage avant d'apprendre qu'elles avaient déjà été inventées) et d'autres structures de données importantes, et je pourrais même connaître quelques astuces qu'ils n'enseignent pas à l'école. Mais je pense que la vérité est que si vous voulez réussir dans ce métier, vous devrez soit faire de l'indé ou apprendre les réponses aux questions qu'ils vous poseront lors des entretiens.
Soit dit en passant, j'ai récemment interviewé pour un rôle de développeur Web frontal. Ils m'ont posé une question où la réponse exigeait à la fois une connaissance de la complexité de calcul et des logarithmes. J'ai réussi à me souvenir de suffisamment de calculs d'il y a vingt ans pour y répondre plus ou moins correctement, mais c'était un peu choquant. Je n'ai jamais eu à utiliser de logarithmes dans aucun développement frontal.
Bonne chance à toi!
la source
La question est assez subjective, donc je pense que la réponse est que cela dépend .
Peu importe si vous travaillez avec de petites quantités de données. Dans ces cas, il est généralement bon d'utiliser par exemple la bibliothèque standard de votre langue.
Cependant, lorsque vous traitez de grandes quantités de données, ou pour une autre raison, vous insistez pour que votre programme soit rapide, vous devez comprendre la complexité de calcul. Si vous ne le faites pas, comment savez-vous comment résoudre un problème ou à quelle vitesse il est même possible de le résoudre? Mais comprendre la théorie ne suffit pas pour être un très bon programmeur. Pour produire du code extrêmement rapide, je crois, vous devez également comprendre comment fonctionne par exemple votre machine (caches, disposition de la mémoire, jeu d'instructions) et ce que fait votre compilateur (les compilateurs font de leur mieux, mais ne sont pas parfaits).
En bref, je pense que comprendre la complexité fait de vous un meilleur programmeur.
la source
C'est certainement un problème si quelqu'un qui développe des algorithmes importants ne comprend pas la complexité des algorithmes. Les utilisateurs d'un algorithme s'appuient généralement sur une bonne qualité d'implémentation qui présente de bonnes caractéristiques de performances. Bien que la complexité ne soit pas le seul contributeur aux caractéristiques de performance d'un algorithme, elle est importante. Une personne qui ne comprend pas la complexité des algorithmes est moins susceptible de développer des algorithmes avec des caractéristiques de performances utiles.
C'est moins un problème pour les utilisateurs d'un algorithme, en supposant que les algorithmes disponibles sont de bonne qualité. Cela est vrai pour les développeurs qui utilisent des langages qui ont une bibliothèque standard importante et bien spécifiée - ils ont juste besoin de savoir comment choisir un algorithme qui répond à leurs besoins. Le problème vient du fait qu'il existe plusieurs algorithmes d'un certain type (par exemple, le tri) disponibles dans une bibliothèque, car la complexité est souvent l'un des critères de sélection. Un développeur qui ne comprend pas la complexité ne peut alors pas comprendre la base pour choisir un algorithme efficace pour sa tâche à accomplir.
Ensuite, il y a des développeurs qui se concentrent (à défaut d'une meilleure description) sur des problèmes non algorithmiques. Par exemple, ils peuvent se concentrer sur le développement d'interfaces utilisateur intuitives. Ces développeurs n'auront souvent pas à se soucier de la complexité de l'algorithme bien que, encore une fois, ils puissent s'appuyer sur des bibliothèques ou d'autres codes en cours de développement de haute qualité.
la source
Cela dépend, mais pas de la quantité de données avec lesquelles vous travaillez, mais du type de travail que vous faites, des programmes que vous développez.
Appelons programmeur qui ne connaît pas la complexité conceptuelle du programmeur noobish.
Le programmeur noobish peut faire:
Le programmeur noobish ne devrait pas faire:
Donc, le programmeur noobish va bien, quand vous voulez simplement utiliser des technologies. Donc, quand il s'agit de développer de nouvelles solutions, des technologies personnalisées, etc. Il est préférable d'embaucher un programmeur non noobish.
Cependant, si l'entreprise ne développe pas de nouvelles technologies, elle utilise uniquement celles déjà fabriquées. Il serait inutile de recruter un programmeur compétent et talentueux. La même chose s'applique, si vous ne voulez pas travailler sur de nouvelles technologies et que vous êtes bien en train de mettre des idées de clients dans des conceptions et des programmes utilisant des cadres déjà créés, alors c'est une perte de temps, d'apprendre quelque chose dont vous n'aurez jamais besoin, sauf si c'est votre hobby et que vous aimez les défis logiques.
la source
J'hésite un peu à écrire une réponse ici, mais depuis que je me suis retrouvé à tergiverser sur plusieurs autres [certains de mes commentaires ont été déplacés pour discuter], voici comment je le vois ...
Il y a des niveaux / degrés de connaissances à beaucoup de choses dans l'informatique (et par ce terme, je veux dire à peu près l'union de l'informatique avec la technologie de l'information). La complexité du calcul est sûrement un vaste domaine (Savez-vous ce qu'est OptP? Ou ce que dit le théorème d'Abiteboul-Vianu?) Et admet également beaucoup de profondeur: la plupart des gens avec un diplôme CS ne peuvent pas produire les preuves expertes qui vont dans la recherche publications en complexité computationnelle.
J'oserais honnêtement comparer la situation de savoir quand appliquer des concepts de complexité computationnelle (et savoir quand vous pouvez les ignorer en toute sécurité) avec la pratique quelque peu courante (en dehors du monde Java) d'implémenter du code sensible aux performances en C et insensible aux performances des choses en Python, etc. (En passant, cela a été appelé dans un discours de Julia le "compromis standard" .) Savoir quand vous n'avez pas à penser aux performances vous fait gagner du temps de programmation, ce qui est également un bien assez précieux.
Et un autre point est que la connaissance de la complexité de calcul ne vous permettra pas automatiquement d'optimiser les programmes; vous devez comprendre plus de choses liées à l'architecture comme la localisation du cache, [parfois] le pipelining, et la programmation parallèle / multicœur de nos jours aussi; ce dernier a à la fois sa propre théorie de la complexité et des considérations pratiques; un avant-goût de ce dernier à partir d'un article SOSP 2013 "Chaque schéma de verrouillage a ses quinze minutes de renommée. Aucun des neuf schémas de verrouillage que nous considérons surpasse systématiquement tout autre, sur toutes les architectures ou charges de travail cibles. Strictement parlant, pour rechercher l'optimalité, l'algorithme de verrouillage doit donc être sélectionné en fonction de la plate-forme matérielle et de la charge de travail attendue. "
la source
Si vous ne connaissez pas le big-O, vous devriez l'apprendre. Ce n'est pas difficile et c'est vraiment utile. Commencez par rechercher et trier.
Je remarque que de nombreuses réponses et commentaires recommandent le profilage , et ils signifient presque toujours l' utilisation d'un outil de profilage .
Le problème est que les outils de profilage sont partout sur la carte en termes d'efficacité pour trouver ce dont vous avez besoin pour accélérer. Ici, j'ai énuméré et expliqué les idées fausses dont souffrent les profileurs.
Le résultat est que les programmes, s'ils sont plus grands qu'un exercice académique, peuvent contenir des géants endormis , que même le meilleur profileur automatique ne peut pas exposer. Cette publication montre quelques exemples de la façon dont les problèmes de performances peuvent se cacher des profileurs.
Mais ils ne peuvent pas se cacher de cette technique.
la source