web-dev-qa-db-fra.com

Le big-O est-il vraiment pertinent lorsque vous travaillez dans l'industrie?

Dans chaque interview dans laquelle j'ai participé, j'ai été interrogé sur l'analyse mathématique de la complexité, y compris la notation big-O.

Dans quelle mesure l'analyse Big-O est-elle pertinente pour le développement dans l'industrie? À quelle fréquence l'utilisez-vous vraiment et à quel point est-il nécessaire d'avoir un état d'esprit aiguisé pour le problème?

66
MM01

Ma question est la suivante: quelle est la pertinence de ce test pour le développement dans l'industrie?

Une solide compréhension de la théorie de la complexité de calcul (par exemple, la notation du grand O) est essentielle pour concevoir des algorithmes, des applications et des systèmes évolutifs. Étant donné que l'évolutivité est très pertinente pour l'informatique dans l'industrie, la grande notation O l'est également.

À quelle fréquence l'utilisez-vous vraiment et à quel point est-il nécessaire d'avoir un état d'esprit aiguisé pour le problème?

Cela dépend de ce que vous entendez par "vraiment l'utiliser". D'une part, je ne fais jamais de preuves formelles de complexité de calcul pour le logiciel que j'écris. D'un autre côté, la plupart du temps, je dois gérer des applications où l'évolutivité est une préoccupation potentielle, et les décisions de conception incluent la sélection (par exemple) de types de collection appropriés en fonction de leurs caractéristiques de complexité.

(Je ne sais pas s'il est possible de mettre en œuvre de manière cohérente des systèmes évolutifs sans une solide compréhension de la théorie de la complexité. Je serais enclin à penser que ce n'est pas le cas.)

76
Stephen C

La raison en est qu'elle indique l'évolutivité .

Un processus qui est O (n ^ 2) sera plus mauvais que celui qui est O (n log n), mais meilleur que celui de O (n ^ 3) ou même O (n!).

Si vous ne connaissez pas les différences et quand elles s'appliquent, vous êtes moins apte à choisir les bonnes implémentations de fonctionnalités, ainsi qu'à extrapoler les performances de test aux performances de production.


EDIT: Une comparaison de 48n avec n ^ 3 de http://www.codinghorror.com/blog/2007/09/everything-is-fast-for-small-n.html (qui en c'est de programmer des perles)

enter image description here

36
user1249

Cela dépend de ce que vous faites.

Pour les développeurs Web (comme moi), cela compte généralement beaucoup. Vous souhaitez que les applications Web évoluent. Si votre application a un goulot d'étranglement qui évolue avec O (n ^ 2), et que vous pensez que c'est très bien, car votre serveur peut gérer 1000 utilisateurs simultanés, il semble que vous n'en ayez pas besoin. Le fait est que pour en gérer deux fois plus (ce qui est raisonnablement probable de se produire juste pendant la nuit), vous aurez besoin de 4 fois la puissance de calcul. Idéalement, vous souhaitez que les applications Web évoluent à O (n), car le matériel est bon marché à un rapport utilisateur/serveur constant et raisonnable.

Généralement dans les applications, où vous avez 100 000 objets, un gros O viendra vous manger. Vous êtes extrêmement vulnérable aux pics. Par exemple, je travaille actuellement sur un jeu 3D, qui est une application qui gère des charges de données. Mis à part le rendu, vous avez la vérification des collisions, la navigation, etc. Vous ne pouvez pas vous permettre de suivre le chemin évident. Vous avez besoin d'algorithmes efficaces, vous avez besoin de beaucoup de cache pour que les moins efficaces s'amortissent. Etc.

Bien sûr, si vous faites quelque chose comme créer une application mobile en lançant une interface graphique dans un concepteur d'interface, connectez cela avec certains services Web et c'est tout, alors vous n'aurez jamais de problèmes de complexité. Parce que les services Web que vous appelez s'en occupent déjà.

32
back2dos

Je n'ai en fait jamais appliqué formellement la règle dans ma vie professionnelle.

Cependant, vous devez être familier avec ce concept et l'appliquer de manière intuitive à chaque fois que vous concevez un algorithme.

La règle est:

Vous devriez être assez familier avec la notation O pour pouvoir déterminer, pour une tâche donnée, si elle est nécessaire pour la calculer formellement, ou juste assez pour l'évaluer intuitivement, ou si vous pouvez simplement la sauter complètement. Tout comme de nombreux autres concepts mathématiques de base.

22
Wizard79

Eh bien, peut-être qu'une petite histoire vous explique pourquoi elle est DEFINITIVEMENT IS nécessaire:

Dans un projet sur lequel je travaillais, il y avait un programme chargé d'imprimer toutes sortes de documents (étiquettes, listes de sélection, etc.). Ce programme se composait de deux parties, l'une lisant toutes les données nécessaires de la base de données et les écrivant dans un fichier de style .ini, et une autre partie qui lit ces fichiers et les remplit dans les modèles. Cela fonctionnait assez bien pour les étiquettes et les petites listes (avec seulement quelques champs) mais cela a fonctionné pendant près de 10 minutes lorsqu'il a dû imprimer une "grande" liste de ~ 20 pages. Parce que l'accès à ces fichiers ini a entraîné des temps d'accès O (n²), n étant le nombre de champs à imprimer.

Si les programmeurs originaux de ce programme avaient compris la notation O, ils ne l'auraient jamais fait de cette façon. Remplacer cette stupidité par une table de hachage l'a rendu tellement plus rapide.

10
user281377

Les performances de Big-O sont importantes, mais elles ont été largement internalisées.

La performance Big-O de tri et de recherche n'a pas d'importance, car les gens utilisent généralement ceux fournis par le système, et ceux-ci seront aussi bons qu'ils peuvent l'être (étant donné qu'ils doivent être généralement utiles). Il existe des structures de données qui sont plus efficaces pour différentes choses, mais celles-ci peuvent généralement être sélectionnées sur des principes généraux (et sont généralement intégrées dans des langages modernes). Il existe un certain sens des algorithmes qui évoluent ou non.

Le résultat est que les problèmes formels se posent rarement dans la pratique, mais la pratique est construite sur les mêmes principes.

8
David Thornley

À mon humble avis, de nombreux programmes informatiques laissent de nombreux étudiants se promener là-bas dans les mauvaises herbes. Ces programmes ne communiquent jamais tout à fait la nature de la science du calcul. Les étudiants entrent dans l'industrie, se débattant avec la façon d'appliquer les concepts qu'ils ont appris, avec peu de compréhension de la façon dont ils se rapportent au monde réel.

Je dirais que le cœur de la science du calcul est la capacité de raisonner sur le calcul. Et vous apprenez diverses méthodes et techniques pour le faire, et les appliquez à des problèmes abstraits, qui sont des primitives prototypiques trouvées dans de nombreux problèmes du monde réel. L'astuce consiste à repérer ces primitives prototypiques dans le monde réel, puis à raisonner sur des choses comme l'exactitude, la complexité, le temps, etc., qui, vous en conviendrez, sont de vrais problèmes dont vous devez vous soucier. Un aperçu du comportement des pièces vous donne souvent un aperçu du comportement de l'ensemble. Et les mêmes méthodes et techniques générales peuvent également être appliquées à l'ensemble, mais pas avec la même rigueur que celle accordée à des parties plus petites, bien abstraites et bien définies. Mais en fin de compte, la science du calcul, vous donne la possibilité de prendre raisonnable des décisions sur la façon d'organiser votre calcul, avec un réel aperçu de la façon dont il se comportera dans diverses conditions.

7
Ziffusion

Mémo à soi!:

Moi et beaucoup d'autres nous posons régulièrement cette question.

Je pense que la vraie raison pour laquelle nous posons cette question est parce que nous sommes devenus paresseux.

Ces connaissances ne seront jamais datées ou deviendront obsolètes. Vous ne pouvez pas l'appliquer directement au jour le jour, mais vous l'utiliserez inconsciemment et cela aura un effet positif sur vos décisions de conception. Un jour, cela peut vous faire économiser, à vous ou à d'autres, des heures et des jours de codage.

Comme de plus en plus de problèmes sont encapsulés par des bibliothèques et des outils tiers et sont disponibles pour de plus en plus de développeurs, vous devrez connaître ces connaissances pour vous distinguer des autres et aider à résoudre de nouveaux problèmes.

5
Conor

Pas vraiment. Fondamentalement, la seule fois où j'y pense, c'est lors de l'accès à la base de données. Je regarde généralement le code et je dis "Cela fait n + 1 requêtes, vous devez le changer pour n'en faire que 1 ou 2"

Parce que toutes mes données sont lues dans une base de données et montrées à l'utilisateur, j'essaie de minimiser la quantité de données avec lesquelles je travaille au point où la différence entre un algorithme linéaire et O (n ^ 2) est assez négligeable.

S'il y a un problème, nous profilerons et le corrigerons plus tard.

5
Greg

Trois questions que vous posez et je pense que des réponses abrégées pourraient aider les arguments plus longs donnés jusqu'à présent.

Quelle est la pertinence de ce test pour le développement dans l'industrie?

Dépend de l'industrie.

Partout où la vitesse du code ou l'espace du code est un problème, il est entièrement pertinent pour l'industrie concernée. Souvent, vous devez savoir combien de temps une routine prendra ou combien de mémoire (on/offline) elle nécessitera.

À quelle fréquence l'utilisez-vous vraiment?

Dépend de l'industrie.

Si les performances et la mise à l'échelle ne concernent pas le travail à effectuer, rarement, uniquement en cas de grave insuffisance de performances. Si vous êtes ingénieur pour un système critique très utilisé, tous les jours probablement.

Dans quelle mesure est-il nécessaire d'avoir une mentalité affinée pour le problème?

Entièrement nécessaire.

Vous devrez peut-être l'utiliser tous les jours, ou seulement dans des circonstances extrêmes; mais parfois cela sera nécessaire. De préférence pendant la conception avant qu'un problème n'arrive, plutôt que de profiler désespérément un système d'étouffement.

3
Orbling

Je dirais que c'est très fréquent. Nous ne prouvons généralement pas que quelque chose a un big-O particulier, mais nous avons internalisé l'idée et mémorisé/nous sommes familiarisés avec les garanties big-O pour des structures de données et des algorithmes particuliers, et nous choisissons les plus rapides pour une utilisation particulière. Il est utile d'avoir une bibliothèque remplie de toutes les options, comme la bibliothèque de collections Java ou C++ STL. Vous utilisez implicitement et naturellement big-O tous les jours = lorsque vous choisissez d'utiliser un Java.util.HashMap (O(1) recherche) au lieu d'un Java.util.TreeMap (O(lg n) recherche) et certainement de ne pas exécuter un linéaire recherchez dans Java.util.LinkedList (O(n) recherche) quelque chose où vous n'avez pas besoin d'un accès trié.

Quand quelqu'un choisit une implémentation sous-optimale et que quelqu'un qui sait mieux arrive et voit son code, cela fait partie de notre vocabulaire de les corriger "votre implémentation prend du temps quadratique, mais nous pouvons le faire jusqu'à n-log-n en le faisant de cette façon à la place "aussi naturellement et automatiquement que nous utiliserions la langue anglaise pour commander une pizza.

3
Ken Bloom

Oui

Vous n'aurez peut-être pas à faire d'analyses formelles, mais au moins une compréhension approfondie de l'ordre de complexité des algorithmes - et comment comparer deux algorithmes autour de cela - est essentielle si vous voulez faire un travail non trivial et le faire aboutir.

J'ai travaillé sur deux systèmes différents qui semblaient bien au début du développement, mais qui ont mis le matériel à genoux lors des tests de production, parce que quelqu'un a utilisé un algorithme O (n ^ 2). Et dans les deux cas, le correctif était un changement trivial à un algorithme O(n).

3
Bob Murphy

Il est probablement utilisé dans des endroits où ils développent des API pour la consommation. Le C++ STL est l'une des rares API à imposer des restrictions de complexité à ses algorithmes. Mais pour le programmeur/programmeur/concepteur/architecte travaillant au quotidien, cela ne leur vient pas à l'esprit.

1
sashang

Je n'ai pas trouvé cela important, sauf pour communiquer des idées, et je travaille dans des domaines critiques pour la performance (raytracing, traitement d'image et de maillage, systèmes de particules, moteurs physiques, etc.) et j'ai dû concevoir de nombreux algorithmes et structures de données propriétaires lorsque vous travaillez en R&D. Dans ces domaines, souvent une poignée de structures de données et d'algorithmes très efficaces peuvent produire de nouveaux produits de pointe, tandis que les algorithmes d'hier rendent les produits existants obsolètes, il y a donc toujours une volonté de faire les choses plus efficacement. Cependant, je n'ai jamais publié d'articles sur les algorithmes que j'ai conçus. Ils étaient tous propriétaires. Si je le faisais, j'aurais besoin de l'aide d'un mathématicien pour formuler des preuves et ainsi de suite.

Pourtant, à mon avis, la quantité de travail de calcul par itération présente souvent un intérêt plus immédiat que l'évolutivité de l'algorithme, sauf si l'algorithme évolue vraiment mal. Si quelqu'un propose une technique de pointe pour le lancer de rayons, je suis plus intéressé par les techniques de calcul telles que la façon dont elles représentent et accèdent aux données que la complexité algorithmique, car une évolutivité raisonnable est déjà une donnée dans ce scénario compétitif et innovant. Vous ne pouvez pas être compétitif avec des algorithmes qui ne évoluent pas.

Bien sûr, si vous comparez la complexité quadratique à la linéarité, c'est une énorme différence. Mais la plupart des gens dans mon domaine sont suffisamment compétents pour éviter d'appliquer un algorithme de complexité quadratique sur une entrée épique. Ainsi, l'évolutivité est souvent profondément impliquée, et les questions les plus significatives et intéressantes deviennent comme, "Avez-vous utilisé GPGPU? SIMD? Fonctionne-t-il en parallèle? Comment avez-vous représenté les données? L'avez-vous réorganisé pour le cache-friendly modèles d’accès? Combien de mémoire faut-il? Peut-il gérer ce cas de manière robuste? Différez-vous certains traitements ou faites-vous tout cela d'un seul coup? "

Même un algorithme linéaireithmique peut surpasser un algorithme à temps linéaire si le premier accède à la mémoire selon un modèle plus optimal, par exemple, ou est mieux adapté pour le multithreading et/ou SIMD. Parfois, même un algorithme linéaire peut surpasser un algorithme logarithmique pour ces raisons, et naturellement les algorithmes à temps linéaire surpassent les algorithmes logarithmiques pour les entrées minuscules.

Donc, pour moi, ce qui importe le plus, c'est ce que certaines personnes pourraient appeler des "micro-optimisations", comme les représentations de données (dispositions de la mémoire, les modèles d'accès avec division du champ chaud/froid, etc.), le multithreading, SIMD et parfois GPGPU. Dans un domaine où tout le monde est déjà suffisamment compétent pour utiliser des algorithmes décents à de pointe pour tout avec de nouveaux articles publiés tout le temps, votre avantage concurrentiel en battant les assistants algorithmiques ne vient pas des améliorations de la complexité algorithmique mais plus directes. efficacité de calcul.

Mon domaine est dominé par de brillants mathématiciens, mais pas toujours par ceux qui connaissent le coût de calcul de ce qu'ils font ou par de nombreuses astuces de bas niveau pour accélérer le code. C'est généralement mon avantage sur eux en concevant des algorithmes et des structures de données plus rapides et plus serrés, bien que le mien soit beaucoup moins sophistiqué. Je joue sur ce que le matériel aime, vers les bits et les octets et je fais chaque itération de travail beaucoup moins cher, même si je fais quelques itérations de travail de plus que l'algorithme vraiment sophistiqué - le travail dans mon cas est considérablement moins cher. Le code que j'écris a également tendance à être beaucoup plus simple. Si les gens pensent que les versions micro-optimisées d'algorithmes et de structures de données simples sont difficiles à comprendre et à maintenir, essayez de comprendre et de maintenir une collection d'algorithmes et de structures de données liés au maillage exotiques jamais vus dans l'industrie avec des articles de 20 pages décrivant leurs étapes mathématiquement .

Comme exemple de base, j'ai trouvé une structure de grille simple qui a fini par surpasser un arbre KD dans notre entreprise pour la détection des collisions et la suppression des points redondants. Ma stupide grille brute était tellement moins sophistiquée algorithmiquement et je suis beaucoup plus stupide mathématiquement et algorithmiquement que le gars qui a implémenté l'arbre KD avec sa nouvelle façon de trouver le point médian, mais je viens de régler l'utilisation de la mémoire de ma grille et les modèles d'accès et c'était suffisant pour surclasser quelque chose de beaucoup plus sophistiqué.

Un autre avantage que j'ai qui me permet de survivre dans un domaine dominé par des gens beaucoup plus intelligents que moi est de vraiment comprendre comment fonctionne l'utilisateur, car j'utilise le logiciel que je développe de la même manière. Cela me donne des idées d'algorithmes qui s'alignent vraiment très immédiatement avec les intérêts des utilisateurs. À titre d'exemple de base, la plupart des gens essaient d'accélérer des choses comme la détection de collision en utilisant l'indexation spatiale. J'ai fait une observation simple qui façonne la carrière il y a près de deux décennies pour les modèles organiques que, par exemple, si un personnage place ses mains sur son visage, une structure d'indexation spatiale voudrait devoir diviser les nœuds et faire des mises à jour coûteuses si le personnage puis enleva sa main de son visage. Si, au lieu de cela, vous partitionnez en fonction des données de connectivité plutôt que des positions des sommets, vous pouvez vous retrouver avec une structure hiérarchique stable qui se met à jour très rapidement et n'a jamais besoin de diviser ou de rééquilibrer l'arborescence (n'a qu'à mettre à jour les cadres de délimitation à chaque image d'animation). .. des choses comme ça - des algorithmes qu'un enfant sans fond mathématique lourd pourrait trouver s'ils comprenaient simplement le concept de base, mais ceux qui échappaient aux mathématiciens car ils ne pensaient pas aux choses d'une manière si proche de la façon dont les utilisateurs travaillé et pensaient trop aux propriétés de la géométrie et non à la façon dont la géométrie était couramment utilisée. Je m'entends assez bien en m'appuyant davantage sur les connaissances informatiques générales et les connaissances utilisateur que sur la magie algorithmique. Donc, de toute façon, je n'ai pas vraiment trouvé important de me concentrer sur la complexité algorithmique.

1
user204677

Je ne pense jamais au grand O dans une perspective mathématique, je ne pense jamais du tout au grand O, sauf si on me le demande. Je vois juste un algorithme dans ma tête, et je peux dire s'il est mauvais parce qu'il fait plusieurs boucles dans la mémoire pour chaque N, ou s'il divise et conquiert ou quelque chose comme ça. Si nécessaire, je peux traduire cela en grande notation O en quelques secondes, mais il est plus facile pour moi de simplement savoir comment l'algorithme/conteneur fonctionne avec la mémoire, que de penser à la perspective mathématique.

0
Coder

Oui, la complexité est importante dans l'industrie. Si vous finissez par concevoir quelque chose où un chemin critique évolue en N-carré (doubler le nombre de quelque chose rend le système quatre fois plus chargé), vous atteindrez votre goulot d'étranglement beaucoup plus rapidement que si vous avez quelque chose qui évolue en N.

Cependant, cela n'est généralement pas fait comme une preuve appropriée et formelle que quelque chose est à une complexité donnée, donc avoir une bonne intuition pour la complexité d'un modèle d'opérations est un bon début.

0
Vatine