Ceci est une question purement théorique. Donc, étant donné un délai "infini" pour faire un programme trivial et une connaissance avancée de C et de l'Assemblée, est-il vraiment préférable de faire quelque chose en montage? est «Performance» perdu lors de la compilation C en montage (au code de la machine)? P>
Par performance, je veux dire, les compilateurs C modernes ont-ils un mauvais travail à certaines tâches qui programment directement dans les accessoires d'assemblage? P>
11 Réponses :
Moderne C peut faire un meilleur travail que l'assemblage dans de nombreux cas, car la tenue de la trace de laquelle les opérations peuvent se chevaucher et qui bloquera les autres sont si complexes qu'elle ne peut être assuie que de manière raisonnable par un ordinateur. P>
@Mark: Je ne suis pas en désaccord avec le sentiment de cette réponse, mais pourquoi une assembleuse ne peut-elle pas faire les mêmes optimisations concernant la planification d'instructions que le C compilateur C?
@indiv: Ils peuvent, en théorie. En pratique, cela peut être incroyablement difficile, en particulier pour les CPU ressemblant à la RISC et à la RISC (qui, ces jours-ci, leur est essentiellement tous).
Oui, vous pouvez faire tout ce que le compilateur C peut faire, c'est juste que vous i> devez le faire. Amusez-vous =)
@Steven hors de curiosité, avez-vous un lien avec des statistiques sur le nombre de processeurs RISC? Je crois comprendre que la plupart des ordinateurs de bureau / ordinateurs portables sont, pour la plupart, une variante de x86 et donc cisc
Je n'ai pas trouvé d'informations sur l'état actuel des assembleurs (probablement assez sombre), mais j'ai trouvé un document sur l'assistant d'assemblage IA-64 d'Intel qui optimiserait la planification d'instructions (page 8). Le document traite également de certaines limitations d'optimisation de l'assemblage VS C si quelqu'un est intéressé. télécharger.intel.com/technology/itj/q41999/pdf/assemblable. PDF . Et @ed, je faisais référence à des optimisations pouvant être faites par l'assembleur lors de la traduction de l'assemblage en code de la machine.
@DocGnome: Même supposé des copeaux de Cisc, comme le X86, ont adapté de nombreuses techniques de RISC. Par exemple, il était plus rapide d'utiliser des instructions complexes pour déplacer les octets en masse (MOVESW, etc.), mais il est maintenant plus rapide d'utiliser des techniques de charge / stockage de type RISC.
@Steven Sudit: C'était vrai sur le Pentium, mais à l'époque du Pentium Pro Rep Movswsw Code> était encore plus rapide. Ces instructions sont toujours améliorées - voir ici: lkml.org/lkml/2009/11 / 6/66
@CAF: Merci pour le lien intéressant. On dirait que les choses sont venues dans au moins cet égard. Je soupçonne que mon point sur la difficulté de la planification de la main peut tirer pleinement parti de la pipeline, cependant.
@CAF Savez-vous à quel point cela est à cause des puces modernes X86 et X86-64 étant réellement mises en œuvre comme principalement des architectures de RISC sous les couvertures, avec de nombreuses instructions complexes implémentées en bytecode en termes de ces instructions de base?
+1, et ajouter l'accent à cela: un compilateur moderne sait généralement ce qui est le plus efficace pour des milliers de processeurs différents, y compris ceux qui mettent en œuvre le même ensemble d'instructions. Ce compilateur sait également comment convertir des idiomes classiques et plus faciles à comprendre C dans chaque code le plus efficace de la CPU spécifique, en tenant compte des choses telles que la taille du cache, les profondeurs de pipeline, etc. Les compilateurs ne l'obtiennent pas toujours parfaitement ou De manière approfondie, mais ils contiennent en eux des connaissances d'optimisation approfondie et peuvent appuyer sur l'alimentation informatique à effectuer en quelques secondes d'optimisations que les cerveaux humains ont besoin d'heures pour vérifier.
sauf si vous êtes un expert d'assemblage et (/ ou) en tirant parti des opcodes avancés non utilisés par le compilateur, le compilateur C gagnera probablement. P>
Essayez-le pour le plaisir; -) p>
Les solutions plus réalistes sont souvent de laisser le compilateur C de faire son bit, puis de profiler et, si nécessaire, des sections spécifiques - de nombreux compilateurs peuvent vider une sorte d'IL de bas niveau (ou même "assemblée"). p>
Vous pouvez compiler le C et regarder la sortie de la langue d'assemblage dans le débogueur. Cela vous permet de modifier le C et de répéter le processus jusqu'à ce que vous obteniez le compilateur pour générer le code souhaité.
Vous pouvez également générer un assemblage à partir d'un code d'objet arbitraire avec Objdump. Le support du compilateur n'est pas nécessaire.
En réalité, c peut être plus rapide que l'assemblage dans de nombreux cas, puisque les compilateurs appliquent des optimisations à votre code. Malgré tout, la différence de performance (le cas échéant) est négligeable. P>
Je me concentrerais davantage sur la lisibilité et la maintenabilité de la base de code, ainsi que de savoir si ce que vous essayez de faire est soutenu dans C. Dans de nombreux cas, l'Assemblée vous permettra de faire plus de choses à bas niveau que c ne peut tout simplement pas faire. Par exemple, avec l'assemblage, vous pouvez profiter directement des instructions MMX ou SSE. P>
Donc, à la fin, concentrez-vous sur ce que vous voulez accomplir. N'oubliez pas - le code de la langue de l'assemblage est terrible de maintenir. Utilisez-le uniquement lorsque vous n'avez pas d'autre choix. P>
Utilisez C pour la plupart des tâches et écrivez le code de montage en ligne pour des spécifiques (par exemple, pour tirer parti de SSE, MME, ...) P>
D'accord. Un ami et moi épartais avec des choses carrées de rooty l'autre jour, et ils ont pu écrire du montage pour tirer parti des intrinsions XMM: il a soufflé le code compilé hors de l'eau.
C'était une question théorique demandée, pas une pratique pratique.
Cette question semble découler de la fausse idée que la performance plus élevée est automatiquement meilleure. Il y a trop d'une perspective de niveau supérieur pour rendre l'assemblée meilleure dans le cas général. Même si la performance est votre principale préoccupation, les compilateurs font généralement un meilleur travail créant une assemblée efficace que vous pourriez vous écrire. Ils ont une "compréhension" beaucoup plus large de tout votre code source que vous ne pouviez éventuellement tenir dans votre tête. De nombreuses optimisations peuvent être provenant de ne pas utiliser d'assemblage bien structuré. P>
évidemment il y a des exceptions. Si vous devez accéder directement au matériel, y compris les caractéristiques de traitement spéciales des CPU (E. SSE), puis l'assemblage est la voie à suivre. Cependant, dans ce cas, vous ferez probablement mieux d'utiliser une bibliothèque qui répond à votre problème général plus directement (par exemple, les packages numériques). P>
Mais vous ne devriez vous inquiéter que pour les choses comme celle-ci si vous avez un besoin concret et spécifique pour la performance accrue et vous pouvez montrer que votre assemblée est plus rapide. Les besoins spécifiques en béton comprennent: des problèmes de performance remarqués et mesurent les systèmes embarqués où la performance est une préoccupation de conception fondamentale, etc. P>
Je suis d'accord avec votre point. Sur une note plus claire - ** "Tout votre code source que vous ne pouvez éventuellement tenir dans votre tête" ** et ensuite ils disent ceci sur la mémoire humaine efficace-min-control.com/human-memory-capacity.html
Je vois votre point, mais je voulais dire cette déclaration d'un angle légèrement différent. Ce n'est pas une question de mémoire car il s'agit d'une prise de conscience intuitive de toutes les interactions différentes entre les différents systèmes. Pensez à la cache L1 au lieu de la mémoire flash. :)
C n'est pas inefficace par rapport à quoi que ce soit. C est une langue et nous ne décrivons pas les langues en termes d'efficacité. Nous comparons les programmes em> en termes d'efficacité. C n'écrire pas de programmes; programmeurs em> écrire des programmes. P>
Assembly vous donne une immense flexibilité lorsque vous comparez avec C, et c'est au coût de la programmation du temps. Si vous êtes un programmeur GURU C et un programmeur d'assemblage de gourou, il est possible que vous puissiez être capable de passer un peu plus de jus d'assemblage pour écrire un programme donné, mais le prix de celui qui est pratiquement certain d'être prohibitif. P>
La plupart d'entre nous ne sont pas des gourous dans l'une ou l'autre de ces langues. Pour la plupart d'entre nous, donner la responsabilité du régleur de performance à un compilateur C est une double victoire: vous obtenez la sagesse d'un certain nombre de gourous de montage, les personnes qui ont écrit le compilateur C, avec une immense quantité de temps entre vos mains d'autres corrects et améliorent votre programme C. Vous avez également une portabilité comme bonus. P>
+1. Je pense que cela vaut aussi la peine d'ajouter que l'on ne devient pas simplement un gourou avec Assembly i> par lui-même. On devient un gourou avec ce que l'assemblage fonctionne le mieux pour un programme sur un modèle de processeur donné i>, qui varie non seulement par la charge de travail, mais également par des détails du processeur "transparent" telles que la taille du cache et la taille de la ligne de cache, la performance du prédicteur de la cache , profondeur de pipeline et toutes sortes d'autres détails qui changent "de manière invisible" en dessous de l'instruction se définir. Les compilateurs apportent que les connaissances PER-CPU à tous tant que l'un des contributants prend le temps d'ajouter un soutien. Un gourou humain doit l'apprendre personnellement pour chacun.
Ignorer combien de temps il faudrait pour écrire le code et que vous avez toutes les connaissances nécessaires pour effectuer toute tâche plus efficacement dans les deux situations, le code de montage sera, par définition, être toujours en mesure de se rencontrer ou de surperformer Le code généré par un compilateur C, car le compilateur C doit créer le code de montage pour effectuer la même tâche et ne peut pas tout optimiser; Et tout ce que le compilateur C écrit, vous pouvez également écrire (en théorie) et, contrairement au compilateur, vous pouvez parfois prendre un raccourci car vous en savez plus sur la situation que d'être exprimée en code C. P>
Cependant, cela ne signifie pas qu'ils font un mauvais travail et que le code est trop lent em>; Juste que c'est plus lent em> que possible. Il peut ne pas être plus que quelques microsecondes, mais il peut encore être plus lent. P>
Ce que vous devez vous rappeler est que certaines optimisations effectuées par un compilateur sont très complexes: l'optimisation agressif a tendance à conduire à un code de montage très illisible, et il devient plus difficile de raisonner sur le code. . C'est pourquoi vous l'écririez normalement en C (ou une autre langue) d'abord, puis profilez-le pour trouver des zones de problèmes, puis continuez à optimiser à la main cette pièce de code jusqu'à ce qu'elle atteigne une vitesse acceptable - parce que le coût de la rédaction Tout en montage est beaucoup plus élevé, tout en fournissant souvent peu ou pas d'avantage. P>
Cela dépend. C compilateurs pour Intel fait un très bon travail de nos jours. Je n'étais pas aussi impressionné par les compilateurs pour bras - je pouvais facilement écrire une version de montage d'une boucle interne qui a effectué deux fois plus vite. Vous n'avez généralement pas besoin de montage sur des machines X86. Si vous souhaitez acquérir un accès direct aux instructions SSE, consultez le compilateur intrinsique! P>
Aussi un bon point. Les compilateurs X86 sont bons. D'autres architectures, peut-être pas si bon.
Étant donné un temps infini et une compréhension extrêmement profonde sur la manière dont une CPU moderne vous permet d'écrire le programme "Parfait" (c'est-à-dire les meilleures performances possibles sur cette machine), mais vous devrez envisager, pour toute instruction de votre Programme, comment la CPU se comporte dans ce contexte, des optimisations liées à la pipeline et en cache et à de nombreuses autres choses. Un compilateur est conçu pour générer le meilleur code de montage possible. Vous comprendrez rarement un code de montage généré par complier moderne, car il a tendance à être vraiment extrême. Parfois, les compliers échouent dans cette tâche car ils ne peuvent pas toujours prévoir ce qui se passe. Généralement, ils font un excellent travail mais ils échouent parfois ... p>
reprise ... Connaître C et Assembly ne suffisent absolument pas pour faire un meilleur travail qu'un compilateur dans 99,99% de cas et considéré que la programmation de quelque chose en C peut être 10000 fois plus rapide que la programmation du même programme de montage à Passez un peu de temps optimiser ce que le compilateur s'est trompé dans les 0,01% restants, ne réinventant pas la roue. P>
Cela dépend du compilateur que vous utilisez? Ce n'est pas une propriété de C ou de toute langue. Théoriquement, il est possible de charger un compilateur avec une AI si sophistiquée que vous pouvez compiler PRAGolog sur une langue plus efficace de la machine que GCC peut faire avec c. P>
Cela dépend de 100% sur le compilateur et 0% sur c. P>
Qu'est-ce que cela est que c est écrit comme une langue pour laquelle il est easy em> écrire un compilateur d'optimisation de C -> Assembly et avec l'assemblage, cela signifie que les instructions d'une machine VON NEUMANN. Cela dépend de la cible, certaines langues comme Prolog seront probablement plus faciles à mapper sur des «machines de réduction» hypothétiques. P>
Mais, étant donné que l'assemblage est votre langue cible pour votre compilateur C (vous pouvez techniquement compiler C à Brainfuck ou à HASKELL, il n'y a pas de différence théorique) alors: P>
Non, les compilateurs ne font pas de mauvais travail du tout. La quantité d'optimisation pouvant être comprimée en utilisant l'assemblage est insignifiante pour la plupart des programmes. P>
Ce montant dépend de la façon dont vous définissez le «compilateur C moderne C». Un tout nouveau compilateur (pour une puce vient d'atteindre le marché) peut avoir un grand nombre d'inefficiences qui seront repoussées au fil du temps. Il suffit de compiler certains programmes simples (les fonctions String.H, par exemple) et analysez ce que chaque ligne de code fait. Vous pouvez être surpris par certaines des choses gaspillantes qu'un compilateur C non testé et reconnaît l'erreur avec une simple lecture du code. Un compilateur mature et bien testé et bien optimisé (Think X86) fera un excellent travail de génération d'assemblage, bien qu'un nouveau fera toujours un travail décent. P>
Un compilateur ne peut pas définir "performance" comme une canette humaine. strong> Je comprends que vous avez dit des programmes triviaux, mais même dans les algorithmes les plus simples (utiles), il y aura un compromis entre la taille et la vitesse. Le compilateur ne peut pas faire cela à une échelle à grains plus fine que les drapeaux -Os / -O [1-3], mais un humain peut savoir ce que «meilleur» signifie dans le contexte du but d'un programme. P >
Certaines instructions de montage dépendant de l'architecture ne peuvent pas être exprimées en c. strong> c'est là que les déclarations ASM () sont entrées. Parfois, ce ne sont pas pour l'optimisation du tout, mais simplement parce qu'il n'y a pas de moyen d'exprimer en C que cette ligne doit utiliser, disons, l'opération de test atomique et défini, ou que nous voulons émettre une interruption SVC avec le paramètre codé X. P>
Les points ci-dessus nonobstant, c Les ordres de grandeur sont plus efficaces de programmer et de maîtriser. Si la performance est importante, l'analyse de l'Assemblée sera nécessaire et les optimisations seront probablement trouvées, mais le compromis dans le temps et les efforts de développement méritent rarement l'effort de programmes complexes sur un PC. Pour des programmes très simples qui doivent être aussi rapides que possible (comme un RTO), ou qui ont de graves contraintes de mémoire (comme un achats avec 1 kb de mémoire flash (non écritable) et de 64.detes de RAM), l'assemblage peut être le seul moyen aller. p>
Tous les assemblages n'ont pas de match 1: 1 avec le bytecode - je travaille avec une CPU qui a un «assemblage de haut niveau» que l'assembleur prend.
@Paul Je comprends que vous pouvez utiliser une langue d'assemblage de haut niveau si vous le souhaitez, sur de nombreux processeurs, dont x86 - mais je pense que cela est plus correctement un langage de programmation en soi, non pas assemblé comme la question indiquée. Y a-t-il un «assemblage de niveau bas» disponible pour votre processeur? Même s'il n'y a pas d'assembleur de ce type fourni par le fabricant, la sortie de votre assembleur actuel est simplement codée ensemble de bas niveau.
Il se traduit par un ensemble de bas niveau - mais ce n'est pas vraiment pris en charge pour les utilisateurs. La plupart des trucs de haut niveau consistent à s'effondrer des instructions similaires dans une seule instruction avec une syntaxe plus facile. Il n'a pas de trucs de type de montage macro.