Apprendre à optimiser avec Assembly [fermé]


21

Je suis un étudiant de deuxième année en technologie des jeux informatiques. J'ai récemment terminé mon premier prototype de mon "genre" de pathfinder (qui n'utilise pas A * à la place d'une approche géométrique / reconnaissance de formes, le pathfinder a juste besoin de la connaissance du terrain qui est à ses yeux pour prendre des décisions, car je voulait une IA qui pourrait réellement explorer, si le terrain est déjà connu, alors il marchera facilement le plus court, car le pathfinder a une mémoire de nœuds).

Quoi qu'il en soit, ma question est plus générale: comment commencer à optimiser les algorithmes / boucles / for_each / etc. en utilisant l'Assemblée, bien que des conseils généraux soient les bienvenus. Je recherche spécifiquement de bons livres, car il est vraiment difficile de trouver de bons livres sur ce sujet. Il y a quelques petits articles comme celui-ci , mais il n'y a toujours pas assez de connaissances pour optimiser un algorithme / jeu ...

J'espère qu'il y a un bon livre moderne là-bas, que je ne pouvais tout simplement pas trouver ...


1
Cela ne répond pas directement à votre question, mais un A * exploratoire (dit adaptatif) a été étudié et a de très bonnes performances (ce qui signifie que vous n'aurez pas besoin de l'optimiser à l'aide d'ASM). Jetez un œil à D * Lite .
Jonathan Dickinson

Réponses:


21

Je serai celui qui va à contre-courant ici et je dirai qu'il n'est jamais trop tôt pour en savoir plus sur les optimisations, en particulier les optimisations d'assemblage et, plus important encore, le débogage en assemblage. Je crois que vous en tirerez le maximum d'avantages si vous êtes étudiant (car alors vous avez très peu à perdre [c.-à-d. En termes de temps / argent]) et tout à gagner.

Si vous êtes dans l'industrie et n'êtes pas chargé de bricoler dans l'assemblage, alors ne le faites pas. Sinon, si vous êtes étudiant ou avez du temps en général, je trouverais le temps d'apprendre à désassembler des programmes et voir si je peux trouver une meilleure solution que le compilateur. Si je ne peux pas, peu importe! Je viens d'apprendre à écrire ainsi qu'à compiler et c'est un énorme avantage lorsque vous êtes confronté à un bogue dans le code de version (sans symboles de débogage) et à regarder le démontage parce que c'est la seule chose que vous pouvez regarder.

La réponse

C'est l'une des meilleures ressources que j'ai trouvées pour en savoir plus sur les optimisations.

http://www.agner.org/optimize/

La diatribe

Si vous lisez certains articles de grands développeurs (par exemple, le raisonnement derrière la création d'EASTL et une inspection plus approfondie du code vous mèneront à des commentaires comme celui -ci parce que GCC est terrible à intégrer cette déclaration if qui vous dira, ce que la majorité des les gens vous disent que le compilateur n'a pas toujours raison, EN PARTICULIER dans le développement de jeux) et puis mettez le pied dans l'industrie, vous constaterez que les optimisations sont une chose quotidienne et savoir ce que signifie la sortie de l'assemblage est un gros plus. De plus, les gens ne semblent pas se rendre compte (en particulier sur stackoverflow) que le profilage des jeux est très difficile et pas toujours précis.

Il y a cependant une mise en garde. Vous pouvez passer du temps à optimiser quelque chose et plus tard vous rendre compte que c'était du temps perdu. Mais qu'avez-vous appris? Vous avez appris à ne pas répéter cette même erreur dans une circonstance similaire.

Ce que SO prend maintenant est à mon avis une position religieuse à la déclaration ne pas optimiser jusqu'à ce que vous profiliez et ne vous inquiétez pas, le compilateur sait mieux que vous . Cela entrave l'apprentissage. Je connais des experts de l'industrie qui sont très bien payés (et je veux dire TRÈS bien) pour jouer en assembleur afin d'optimiser le jeu et de le déboguer parce que le compilateur est mauvais ou ne peut tout simplement pas vous aider, car, eh bien, il ne peut pas (plantages liés au GPU, plantages où les données impliquées sont impossibles à lire dans un débogueur, etc., etc.)!

Et si quelqu'un qui aime faire cela, ne l'a pas encore complètement réalisé, pose la question ici et est désactivé / désactivé par les nombreuses réponses que le compilateur connaît mieux que vous! et ne devient jamais l'un de ces programmeurs hautement payés?

Une dernière pensée. Si vous commencez à le faire tôt, vous constaterez que bientôt vous commencerez à écrire du code qui est au pire, n'a aucune amélioration des performances parce que le compilateur l'a optimisé de la même manière ou au mieux, a quelques améliorations de performances car maintenant le compilateur peut l'optimiser . Dans les deux cas, c'est devenu une habitude, et vous n'êtes pas plus lent à écrire du code de cette façon que ce que vous avez fait auparavant. Quelques exemples sont (il y en a beaucoup plus):

  1. Pré-incrémentation sauf si vous voulez vraiment post-incrémentation
  2. Écriture de boucles pour les conteneurs à l'aide d'une variable de taille locale constante plutôt que d'appeler size () sur le conteneur dans la boucle.

EDIT: mise à jour après 8 ans de plus dans l'industrie. Apprenez l'assemblage. Apprenez comment les optimiseurs fonctionnent et l'assemblage qu'ils génèrent (CompilerExplorer est un excellent outil pour cela). J'ai rencontré d'innombrables plantages dans les versions de test (versions optimisées pour les tests internes) où vous ne pouvez pas compter sur le débogueur même avec des symboles de débogage. Le compilateur a optimisé trop de choses et l'assembly est votre seule source d'informations précieuses pour trouver le bogue du crash dump. Chaque build prend 30 à 40 minutes si vous êtes chanceux et premier dans la file d'attente de build - vous ne pouvez donc pas compter sur certaines techniques traditionnelles pour isoler le bogue. Le multijoueur aggrave les choses. Connaître l'assemblage et savoir lire l'assemblage optimisé vous rendra simplement meilleur et finalement plus précieux pour l'équipe.


1
Bon point sur l'optimisation des compilateurs. Ils sont excellents, mais ils sont loin d'être parfaits, et contrairement à ce que certains croient, il n'est généralement pas difficile de trouver une optimisation simple qu'un compilateur n'a pas faite.
aaaaaaaaaaaa

3
Il convient de noter qu'il existe une différence entre "apprendre à lire l'assemblage" et "apprendre à optimiser avec l'assemblage". Les deux ne sont pas la même chose, et votre réponse ne concerne pas vraiment l'utilisation de l'assemblage pour implémenter des optimisations. La lecture de l'assemblage est une compétence utile, car elle peut aider à déboguer et à repérer les endroits où le compilateur ne fait pas quelque chose de bien. Mais cela est très différent de l'utilisation réelle de l'assemblage pour écrire des routines optimisées, ce qui nécessite une connaissance approfondie de la planification des instructions pour un processeur spécifique. Et c'est aussi quelque chose que vous n'avez pas couvert.
Nicol Bolas

1
En outre, "Je viens d'apprendre à écrire ainsi que le compilateur" Non, vous ne l'avez pas fait. Vous avez regardé comment une routine spécifique a été compilée pour un processeur spécifique. Apprendre à implémenter des routines d'assemblage optimisées nécessite plus que de regarder comment le compilateur a compilé une seule routine. Vous devez comprendre pourquoi le compilateur a choisi ces opcodes dans cet ordre pour reproduire ce code C ++ spécifique. Et cela nécessite une connaissance approfondie du processeur, de la planification des instructions, etc. Généraliser cela nécessite des années d'expérience; vous ne l'obtiendrez pas en décodant simplement quelques routines.
Nicol Bolas

7
Donc, -1 pour A: ne répond pas réellement à la question sur la façon d'écrire des routines optimisées pour l'assemblage. B: déformer à quel point il est facile d'apprendre à battre le compilateur lors de l'écriture de routines optimisées pour l'assemblage. Et C: encourager un programmeur à regarder les optimisations au niveau de l'assembly avant les optimisations au niveau de l' algorithme. Même ces «experts de l'industrie» très bien payés vous diraient que cela met la charrue avant le cheval.
Nicol Bolas

2
@Samaursa: Personne n'a dit que les gens ne devraient pas "comprendre le désassemblage et comment optimiser le code". Ce n'est pas un débat religieux; c'est une question de simple fait. Les gens ont passé des siècles à optimiser manuellement une routine pour découvrir que cela ne signifie rien pour la performance globale. Apprendre à optimiser les algorithmes est un ensemble de compétences très précieux. Apprendre à lire l'assemblage est une compétence semi-précieuse. Apprendre à écrire des routines d'assemblage est un ensemble de compétences qui n'est que rarement utilisé. Et de nos jours, les meilleures optimisations proviennent d'une meilleure utilisation du cache, et non d'un assemblage manuel.
Nicol Bolas

22

Le premier conseil que vous obtiendrez est le suivant - ne le faites pas.

Les compilateurs modernes sont en fait vraiment très bons pour optimiser le code, et seront beaucoup plus susceptibles d'en faire un meilleur travail que n'importe quel langage d'assemblage auto-roulé que vous pourriez écrire.

L'exception serait tout cas spécifique où vous avez déterminé avec certitude que le compilateur fait un mauvais travail d'optimisation, c'est donc la deuxième astuce. Il n'y a pas de directives générales ici, vous devez connaître votre propre code, savoir ce qu'il fait, être capable de sauter dans un démontage de celui-ci et être en mesure de déterminer avec une certitude absolue que le compilateur fait du mauvais travail.

Même dans ce cas, vous ne le souhaiterez peut-être pas. Vous devez être certain qu'il n'y aura pas de frais généraux de maintenance continue pour vous. Vous souhaiterez peut-être revenir à ce code dans 6 mois et en modifier une partie, ou vous pouvez trouver un bogue extrêmement subtil qui sera plus difficile à corriger dans une version en langage assembleur. Même si vous pensez que vous avez résolu tous les bogues, une fois que votre programme est passé aux bogues publics que vous n'auriez jamais pensé que cela pourrait se produire, cela deviendra une réalité pour vous. C'est une révélation (et une expérience humiliante).

Et même si vous êtes heureux d'accepter cela, vous constaterez peut-être qu'il n'y a absolument aucune amélioration mesurable des performances car votre goulot d'étranglement principal pourrait être quelque part complètement différent dans votre programme. Cela me ramène donc à nouveau au numéro 1. Non.


15

Habituellement, une optimisation solide ne dépend pas de l'utilisation de Assembly ou de la réalisation de micro-optimisations avec du code dans des langages de niveau supérieur. Si vous lisez beaucoup d'articles de recherche (comme moi - ou essayez!), Vous verrez que souvent les améliorations apportées aux algorithmes se situent à un niveau conceptuel plus large, "qualitatif", plutôt qu'à un niveau plus "quantitatif". niveau de micro-optimisation. Je voudrais souligner que les gains d'ordre de grandeur sont plus susceptibles d'être trouvés en examinant les algorithmes de ce point de vue, ou en vectorisant / parallélisant les solutions existantes.

Cela dit, je suis récemment tombé sur cela , ce qui peut être une bonne voie vers l'apprentissage de l'ASM x86 spécifiquement pour les développeurs de jeux.


ADDENDA

Deux sources au sommet de ma tête:

De plus, la lecture de documents de recherche est un excellent moyen de suivre les processus de réflexion des sages car ils optimisent les algorithmes pour de meilleures performances. Le plus souvent, les gains sont constatés par:

  • Réduire l'utilisation des opérations les plus coûteuses (div, SQRT, trig ops et conditionals, principalement);
  • Amélioration des performances du cache grâce à l'utilisation de structures de données plus efficaces, l'alignement de la mémoire et des conditions réduites;
  • Réduire la qualité de la production dans des zones acceptables pour de meilleures performances;
  • Vectorisation (SIMD);
  • Parallélisation (threading, comprend le déplacement des tâches vers le GPU);
  • Et bien sûr (de plus en plus rarement) un assemblage codé à la main. D'abord, inspectez les assemblages C / C ++ pour voir où le compilateur fait des choix non optimaux, bien sûr. Vous en trouverez plus dans des articles plus anciens des années 80 et 90, IME.

La recherche en lecture vous permet également de rester à la fine pointe de votre domaine, au lieu d'attendre que ces connaissances s'infiltrent dans l'industrie.


vous parlez d'optimisation d'algorithme mais vous ne donnez aucune information à ce sujet, si nous devions suivre vos conseils et regarder cela à la place, pourriez-vous donner une direction?
Skeith

En fait, je le mentionne; vous devez étudier les algorithmes, comprendre ce que les informaticiens font pour améliorer qualitativement les performances. Plongez-vous suffisamment dans cela et avec le temps, vous commencez à penser en termes similaires. Les efforts supplémentaires ici portent leurs fruits, contrairement aux années passées (et j'ai récemment vu cela mentionné sur un forum ASM) maîtriser les tenants et aboutissants de (juste) par exemple. Architecture x86. Chassez le gros gibier: apprenez à réduire les problèmes à leur cœur, puis décidez ce qui est superflu pour l'optimiser. Voir les livres de référence ci-dessus.
Ingénieur

@NickWiggill Quelle est votre source habituelle de documents de recherche?
kizzx2

3

Je pense qu'il pourrait être trop tôt.

Quoi qu'il en soit, il est important de comprendre que le compilateur lui-même ne produit pas de code plus lent que l'équivalent d'assembly, vous n'obtenez aucune performance simplement en écrivant le même code d'assembly que le compilateur.

Pour commencer, concentrez-vous au moins sur des optimisations sans assemblage. Igor Ostrovsky a quelques bons articles qui démontrent certaines des bases: http://igoro.com/archive/fast-and-slow-if-statements-branch-prediction-in-modern-processors/

Notez que les erreurs de prédiction de branche et les erreurs de cache sont ce que vous devez principalement optimiser, même si vous devez payer en effectuant des opérations arithmétiques supplémentaires, cela vaut généralement la peine d'éviter une branche imprévisible ou de lire au hasard à partir de trop de mémoire.

Et bien sûr, surtout, optimisez d'abord votre algorithme. Une implémentation lente d'un algorithme rapide sera presque toujours plus rapide qu'une implémentation rapide d'un algorithme lent.


2

Ce livre est exceptionnellement bon pour un livre de texte. Mais ce n'est pas spécifiquement orienté vers l'optimisation. Langage d'assemblage pour processeurs x86, 6e édition

Il s'agit davantage d'enseigner les principes fondamentaux de l'assemblage, en utilisant MASM. Ensuite, vers la fin du livre, il explique comment intégrer l'assemblage avec c ++ et l'intégrer dans des programmes plus importants.

Je mets cela ici parce qu'il est logique d'apprendre les principes fondamentaux de l'assemblage avant d'apprendre à optimiser les programmes avec.

J'aime ce livre car Irvine vous apprend à utiliser les outils nécessaires pour écrire des programmes de masm. Il explique spécifiquement comment utiliser l'IDE (Visual Studio C ++) et le débogueur. Chaque chapitre contient quelques vidéos dédiées à la résolution de problèmes. Certaines de ces informations sont disponibles gratuitement sur le site Internet répertorié.


1
"il est logique d'apprendre les principes fondamentaux de l'assemblage avant d'apprendre à optimiser les programmes avec elle" - de bons conseils.
Maximus Minimus
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.