Quand est-assemblage plus rapide que le C?
L'une des raisons pour connaître l'assembleur, c'est que, à l'occasion, il peut être utilisé pour écrire du code qui sera plus performant que d'écrire ce code dans un langage de niveau plus élevé, C en particulier. Cependant, j'ai aussi entendu il dit à plusieurs reprises que, même si c'est pas entièrement faux, le cas où l'assembleur peut fait être utilisé pour générer plus de code performant sont à la fois extrêmement rares et requièrent une expertise et une expérience de l'assemblée.
Cette question n'a même pas entrer dans le fait que les instructions de l'assembleur sera spécifique à la machine et non portable, ou l'un des autres aspects de l'assembleur. Il ya beaucoup de bonnes raisons pour savoir assemblée d'ailleurs celui-ci, bien sûr, mais c'est censé être une question spécifique de la sollicitation d'exemples et de données, pas une extension de discours sur l'assembleur versus langues de plus haut niveau.
Quelqu'un peut-il fournir certains des exemples précis de cas où l'assemblée sera plus rapide que le bien-écrit le code en C à l'aide d'un compilateur moderne, et pouvez-vous soutenir cette affirmation avec le profilage des données probantes? Je suis assez confiant sur le fait que ces cas existent, mais je veux vraiment savoir exactement comment ésotérique de ces cas, car il semble être un point de discorde.
- Et maintenant, une autre question serait approprié: Quand est-ce le fait que l'assembleur est plus rapide que C effectivement des questions?
- L'une des plus grandes questions que j'ai vu. Merci Adam!
- Comme quelqu'un juste au début pour apprendre l'asm, je trouve les réponses à cette question très utile.
- en fait, il est tout à fait banale pour améliorer le code compilé. N'importe qui avec une solide connaissance du langage assembleur et C peut le voir en examinant le code généré. Tout facile est la première performance de la falaise vous tombez d'lorsque vous exécutez hors de jetables registres dans la version compilée. En moyenne, le compilateur va faire beaucoup mieux qu'un homme pour un gros projet, mais il n'est pas difficile dans une taille convenable du projet pour trouver des problèmes de performances dans le code compilé.
- En fait, la réponse courte est: Assembleur est toujours le plus rapide ou égale à la vitesse de C. La raison en est que vous pouvez avoir de l'assemblée sans C, mais vous ne pouvez pas avoir C sans montage (dans la forme binaire, qui nous l'ancien des jours "code machine"). Cela dit, la réponse est: les Compilateurs C sont assez bon dans l'optimisation et la "pensée" à propos de choses que vous n'avez pas l'habitude de penser, donc cela dépend vraiment de vos compétences, mais normalement, vous pouvez toujours battre le compilateur C; il est encore seulement un logiciel qui ne peut pas penser et d'avoir des idées. Vous pouvez aussi écrire à l'assembleur portable si vous utilisez des macros et vous êtes patient.
- Je suis en total désaccord que les réponses à cette question doivent être "opinion fondée" - ils peuvent tout à fait objectif - il n'est pas quelque chose comme essayer de comparer les performances de l'animal de compagnie préféré des langues, dont chacune a des points forts et des inconvénients. C'est une question de comprendre dans quelle mesure les compilateurs peuvent nous prendre, et à partir de quel moment il est préférable de prendre le dessus.
- Il n'est même pas toujours le cas que vous avez besoin de réécrire quelque chose dans l'assemblage de récolter les avantages de la connaissance de l'assemblée. Simplement recompiler votre C de l'algorithme dans diverses formes et en observant l'assemblée que le compilateur génère va vous permettre d'écrire plus efficace du code en C.
- Pour un ésotérisme exemple, de faire une recherche sur le web pour
pclmulqdq crc
. pclmulqdq est une assemblée spéciale de l'instruction. L'optimisation des exemples d'utilisation environ 500 lignes de code assembleur. Certains X86 ont également uncrc32c
instruction pour un cas spécifique de crc32. Les résultats d'un Benchmark pour générer crc32 de plus de 256 MO (256*1024*1024) tableau d'octets: c code à l'aide de la table => 0.516749 sec, assemblage à l'aide de pcmuldq => 0.0783919 sec, code c à l'aide de crc32 intrinsèque => 0.0541801 sec. - Plus tôt dans ma carrière, j'ai écrit beaucoup de C et mainframe assembleur à une société de logiciels. Un de mes camarades était ce que j'appellerais un "assembleur puriste" (tout devait être assembleur), de sorte que je parie que lui, je pourrais écrire une routine qui courait plus vite en C que ce qu'il a pu écrire en assembleur. J'ai gagné. Mais pour couronner le tout, après j'ai gagné, je lui ai dit que je voulais un deuxième pari - que je pourrais écrire quelque chose de plus rapide dans l'assembleur que le programme C qui l'a battu sur l'état de la mise. Je ne vais que trop, prouvant que la plupart de la compétence et de la capacité du programmeur plus de anythings d'autre.
- À moins que votre cerveau a une
-O3
drapeau, vous êtes probablement mieux de laisser l'optimisation du compilateur C 🙂
Vous devez vous connecter pour publier un commentaire.
Voici un exemple réel: point Fixe se multiplie sur les anciens compilateurs.
Ces ne viennent pas seulement pratique sur les appareils sans virgule flottante, ils brillent quand il s'agit de précision car ils vous donnent des 32 bits de précision avec un prévisible d'erreur (float a seulement 23 bits et il est plus difficile de prédire la perte de précision due). c'est à dire uniforme absolue de précision sur l'ensemble de la gamme, au lieu de la fin-de-uniforme relative de précision (
float
).Les compilateurs modernes optimiser ce point fixe, exemple bien, donc, pour plus d'exemples modernes qui ont encore besoin de compilateur de code spécifiques, voir
uint64_t
pour 32x32 => 64-bit multiplie échoue à optimiser sur un PROCESSEUR 64 bits, si vous avez besoin intrinsèques ou__int128
pour un code efficace sur les systèmes 64 bits.C ne pas disposer d'un opérateur de multiplication (2N bits suite de N bits d'entrées). La manière habituelle de l'exprimer dans C est de jeter les entrées à l'ensemble de la type et espère que le compilateur reconnaît que les bits de poids à l'une des entrées ne sont pas intéressants:
Le problème avec ce code, c'est que nous faisons quelque chose qui ne peut pas être directement exprimée dans le langage C. Nous voulons multiplier deux 32 bits et d'obtenir un 64 bits à la suite de laquelle nous retourner le milieu de 32 bits. Toutefois, dans C cette multiplier n'existe pas. Tout ce que vous pouvez faire est de promouvoir les entiers de 64 bits et faire un 64*64 = 64 multiplier.
x86 (et ARM, MIPS et d'autres) peuvent toutefois faire l'multiplier en une seule instruction. Certains compilateurs utilisés pour ignorer ce fait et de générer du code qui appelle une fonction de bibliothèque runtime pour faire le multiplier. Le passage par 16 est également souvent fait par une routine de bibliothèque (qui est aussi le x86 pouvez faire ces changements).
Alors on se retrouve avec un ou deux appels de bibliothèque juste pour se multiplier. Ce qui a de graves conséquences. Non seulement le changement plus lent, les registres doivent être conservés à travers les appels de fonction et il n'aide pas l'in-lining et un code-dérouler soit.
Si vous réécrire le même code (inline) assembleur, vous pouvez gagner une importante augmentation de la vitesse.
En plus de cela: à l'aide de l'ASM n'est pas la meilleure façon de résoudre le problème. La plupart des compilateurs de vous permettre d'utiliser certaines des instructions en assembleur dans intrinsèque de la forme si vous ne pouvez pas exprimer par des C. La VS.NET2008 compilateur par exemple expose le 32*32=64 bits mul qu' __emul et le 64 bits maj __ll_rshift.
À l'aide de intrinsèques vous pouvez réécrire la fonction en sorte que le compilateur C a une chance de comprendre ce qu'il se passe. Cela permet au code inline, registre alloué, commune de la sous-expression de l'élimination et de la constante de propagation peut être fait aussi bien. Vous recevrez un énorme amélioration des performances sur les écrits à la main de code en langage assembleur de cette façon.
De référence: Le résultat final pour le point fixe mul pour l'VS.NET compilateur:
La différence de performance de point fixe divise encore un peu plus. J'ai eu des améliorations jusqu'à facteur de 10 pour la division des lourds point fixe code par l'écriture d'un couple de l'asm-lignes.
À l'aide de Visual C++ 2013 donne le même code d'assemblée pour les deux façons.
gcc4.1 à partir de 2007 optimise également la pure version C bien. (Le Godbolt compilateur explorer n'a pas les anciennes versions de gcc installé, mais sans doute encore plus anciennes versions de GCC pourrait le faire sans intrinsèques.)
Voir la source + asm x86 (32 bits) et le BRAS le Godbolt compilateur explorer. (Malheureusement il n'a pas de compilateurs assez vieux pour produire de mauvais code de la simple version C.)
Processeurs modernes peuvent faire des choses C n'ont pas les opérateurs pour à tous les, comme
popcnt
ou bit-numérisation de trouver le premier ou le dernier bit à. (POSIX a unffs()
fonction, mais sa sémantique ne correspondent pas x86bsf
/bsr
. Voir https://en.wikipedia.org/wiki/Find_first_set).Certains compilateurs peuvent parfois reconnaître une boucle qui compte le nombre de bits d'un entier et de le compiler pour un
popcnt
instruction (si elle est activée au moment de la compilation), mais il est beaucoup plus fiable à utiliser__builtin_popcnt
dans C de GNU, ou sur x86, si vous n'êtes ciblage matériel avec SSE4.2:_mm_popcnt_u32
par<immintrin.h>
.Ou en C++, de lui attribuer un
std::bitset<32>
et l'utilisation.count()
. (C'est un cas où la langue a trouvé un moyen d'exposer de façon portable d'une optimisation de la mise en œuvre de popcount par le biais de la bibliothèque standard, de façon à toujours compiler à quelque chose de correct, et peut profiter de ce que la cible prend en charge.) Voir aussi https://en.wikipedia.org/wiki/Hamming_weight#Language_support.De même,
ntohl
pouvez compiler pourbswap
(x86 32-bit byte swap pour la conversion "endian") sur certaines implémentations C qui l'ont.Un autre domaine important pour l'intrinsèques ou écrites à la main, l'asm est le manuel de la vectorisation avec des instructions SIMD. Les compilateurs ne sont pas mauvais avec de simples boucles comme
dst[i] += src[i] * 10.0;
, mais souvent mal ou de ne pas auto-vectorisation du tout quand les choses deviennent plus compliquées. Par exemple, vous êtes peu probable d'obtenir quelque chose comme Comment mettre en œuvre atoi à l'aide SIMD? généré automatiquement par le compilateur à partir de scalaire code.#if #else
pré-processeur de déclaration.uint_quotient=ulong_dividend/uint_divisor
dans le cas où ulong_dividend est connu pour être de moins de 2^32 fois uint_divisor?)__ll_rshift
est un C de construire! Compilateur spécifique bien, mais pas à l'asm.asm()
appels. De cette façon, le compilateur est capable d'allouer des registres au moment de la construction.Il y a plusieurs années j'ai été l'enseignement de quelqu'un pour programmer en C. L'exercice était de faire pivoter un graphique de 90 degrés. Il revint avec une solution qui a pris plusieurs minutes, surtout parce qu'il était l'aide de multiplie et divise etc.
Je lui ai montré comment la refonte du problème à l'aide de bits quarts de travail, et le temps de traitement est descendu à environ 30 secondes sur la non-optimisation du compilateur qu'il avait.
J'avais juste eu un compilateur optimisant et le même code de la rotation de l'image dans < les 5 secondes. J'ai regardé à l'assemblée, le code que le compilateur génère, et de ce que j'ai vu a décidé il y et alors que mes journées de l'écriture de l'assembleur étaient plus.
add di,di / adc al,al / add di,di / adc ah,ah
etc. pour l'ensemble des huit registres de 8 bits, puis faire tous les 8 registres de nouveau, puis répétez l'ensemble de la procédure trois fois de plus, et enfin enregistrer quatre mots dans ax/bx/cx/dx. Aucun moyen d'un assembleur est proche.Peu près n'importe quand le compilateur voit du code de nombres flottants, une main version écrite sera plus rapide. La raison principale est que le compilateur ne peut pas effectuer toutes robuste optimisations. Voir cet article de MSDN pour une discussion sur le sujet. Voici un exemple où la version de l'assembly est deux fois plus rapide que la version C (compilé avec VS2K5):
Et certains numéros de mon ordinateur exécutant une version par défaut de construire*:
D'intérêt, j'ai remplacé la boucle avec un dec/jnz et il ne fait pas de différence pour les périodes de temps - parfois plus vite, parfois plus lent. Je suppose que la mémoire de l'aspect limité des nains d'autres optimisations.
Oups, j'ai du courir un peu différente de la version du code, et il achera les chiffres à l'envers (c'est à dire C est plus rapide!). Corrigés et mis à jour les résultats.
-ffast-math
. Ils ont un niveau d'optimisation,-Ofast
qui est actuellement équivalent à-O3 -ffast-math
, mais dans l'avenir, il y a plus d'optimisations qui peuvent conduire à des erreurs de génération de code en cas de coin (telles que le code qui s'appuie sur la norme IEEE NaNs).a+b == b+a
), mais pas associatif (réorganisation des opérations, de l'arrondissement des intermédiaires est différent). re: code: je ne pense pas décommenté x87 et unloop
l'enseignement sont d'une très impressionnante démonstration de rapidité de l'asm.loop
est apparemment pas fait un goulot d'étranglement en raison de la FP de latence. Je ne suis pas sûr si il est pipelining FP opérations ou pas; x87 est difficile pour les humains de lire. Deuxfstp results
insns à la fin est clairement pas optimal. Popping supplémentaires résultent de la pile serait mieux fait avec un non-store. Commefstp st(0)
IIRC.Sans donner d'exemple précis ou d'un profileur de preuves, vous pouvez écrire mieux assembleur que le compilateur lorsque vous en savez plus que le compilateur.
Dans le cas général, un moderne compilateur C en sait beaucoup plus sur la façon d'optimiser le code en question: il sait comment du pipeline du processeur travaille, il peut essayer de réorganiser les instructions plus rapide qu'un humain peut le faire, et ainsi de suite - c'est fondamentalement la même que celle d'un ordinateur d'être aussi bon ou meilleur que le meilleur joueur humain pour les jeux de société, etc. tout simplement parce qu'il peut faire des recherches au sein de l'espace de problème plus rapidement que la plupart des humains. Bien que théoriquement vous pouvez effectuer ainsi que l'ordinateur dans un cas particulier, vous ne pouvez certainement pas à la même vitesse, ce qui rend impossible pour plus de quelques cas (c'est à dire le compilateur va très certainement surpasser si vous essayez d'écrire plus de quelques routines en assembleur).
D'autre part, il existe des cas où le compilateur n'a pas autant d'informations, je dirais, surtout lorsque l'on travaille avec les différentes formes de matériel externe, dont le compilateur n'a pas connaissance. L'exemple principal étant probablement les pilotes de périphériques, où assembleur combiné avec un homme de connaissance intime du matériel en question peut donner de meilleurs résultats qu'un compilateur C pourrait le faire.
D'autres ont mentionné des fins spéciales instructions, qui est ce que je parle dans le paragraphe ci-dessus - les instructions de laquelle le compilateur peut avoir peu ou pas de connaissances à tous, ce qui rend possible pour un être humain d'écrire plus rapidement le code.
ocamlopt
ignore la planification d'instructions x86 et, au lieu de cela, laisse le CPU, car il peut réorganiser de manière plus efficace au moment de l'exécution.Dans mon travail, il y a trois raisons pour moi de connaître et d'utiliser de l'assemblée. Dans l'ordre d'importance:
De débogage - je reçois souvent de la bibliothèque de code qui a des bugs ou incomplète de la documentation. Je figure sur ce qu'il fait en marchant sur au niveau de l'assemblage. Je dois le faire une fois par semaine environ. J'ai aussi l'utiliser comme un outil pour déboguer les problèmes liés à mes yeux de ne pas repérer la idiomatiques erreur en C/C++/C#. En regardant l'assemblée obtient passé.
Optimiser - le compilateur ne assez bien dans l'optimisation, mais j'ai jouer dans un autre stade que la plupart. J'écris de traitement d'image de code qui commence généralement avec un code qui ressemble à ceci:
le "faire partie de" ce qui se passe généralement de l'ordre de plusieurs millions de fois (c'est à dire, entre 3 et 30). En grattant les cycles que "faire quelque chose" phase", les gains de performance sont extrêmement amplifié. Je n'ai pas l'habitude de commencer là - bas- j'ai l'habitude de commencer par écrire le code de travail d'abord, puis de faire de mon mieux pour refactoriser le C naturellement mieux (meilleur algorithme, moins de charge dans la boucle, etc). Habituellement, j'ai besoin de lire l'assemblée pour voir ce qu'il se passe et rarement besoin de l'écrire. Je le fais peut-être tous les deux ou trois mois.
de faire quelque chose de la langue ne me laisse pas. Il s'agit - l'obtention de l'architecture du processeur et processeur spécifique de caractéristiques, l'accès à des drapeaux pas dans la CPU (homme, je souhaite vraiment que C vous a donné accès à la retenue), etc. Je le fais peut-être une fois par an ou de deux ans.
Uniquement lors de l'utilisation de certains à des fins spéciales d'instruction définit le compilateur ne prend pas en charge.
Afin de maximiser la puissance de calcul d'un PROCESSEUR récent avec plusieurs pipelines et de prédiction de branchement vous avez besoin de la structure de l'assemblée programme d'une manière qui le rend presque impossible pour un être humain d'écrire b) d'autant plus impossible à maintenir.
Aussi, de meilleurs algorithmes, structures de données et de gestion de la mémoire vous donnera au moins un ordre de grandeur plus de performances que les micro-optimisations que vous pouvez faire dans l'assemblée.
Bien que C est "proche" du faible niveau de la manipulation de 8 bits, 16 bits, 32 bits, 64 bits de données, il y a quelques opérations mathématiques sont pas pris en charge par C, ce qui peut souvent être réalisée d'une manière élégante dans certains assemblée de jeux d'instructions:
Point fixe de multiplication: Le produit de deux nombres 16 bits est un nombre de 32 bits. Mais les règles en C dit que le produit de deux nombres 16 bits en 16 bits, et le produit de deux nombres de 32 bits est un nombre de 32 bits -- le fond de la moitié dans les deux cas. Si vous voulez le haut la moitié de 16x16 multiplier ou 32x32 se multiplient, vous avez à jouer à des jeux avec le compilateur. La méthode générale consiste à lancer à un plus grand que nécessaire bits largeur, multipliez, décalage vers le bas, et le jeta en arrière:
Dans ce cas, le compilateur peut être assez intelligent pour savoir que vous êtes vraiment juste essayer d'obtenir la moitié supérieure de 16x16 de se multiplier et de faire la bonne chose avec la machine natif 16x16multiply. Ou il est peut-être stupide et nécessitent un appel de la bibliothèque pour faire le 32x32 multiplier de façon exagéré, car vous avez seulement besoin de 16 bits du produit -- mais le C standard ne vous donne pas de toute façon de vous exprimer.
Certains bitshifting opérations (rotation/porte):
Ce n'est pas trop inélégant en C, mais encore une fois, à moins que le compilateur est assez intelligent pour savoir ce que vous faites, il va faire beaucoup de "inutiles" les travaux. De nombreux assemblée jeux d'instructions vous permettent de faire pivoter ou de décalage gauche/droite avec le résultat dans le report de registre, de sorte que vous pourriez accomplir dans 34 instructions: charger un pointeur vers le début du tableau, claire de le porter, et effectuer des 32 8-bits à droite-quarts, à l'aide de l'auto-incrémentation du pointeur.
Pour un autre exemple, il y a registres à décalage à rétroaction linéaire (LFSR) qui sont élégamment réalisé dans le montage: Prendre un bloc de N bits (8, 16, 32, 64, 128, etc), modifier l'ensemble du droit de chose par 1 (voir l'algorithme ci-dessus), puis si le portage est de 1, alors vous XOR dans une séquence de bits qui représente le polynôme.
Cela dit, je n'aurais pas recours à ces techniques, à moins que j'ai eu grave les contraintes de performances. Comme d'autres l'ont dit, le montage est beaucoup plus difficile de document/debug/test/entretien que le code C: le gain de performance est livré avec certains des coûts importants.
edit: 3. Détection de débordement est possible dans l'assemblée (ne peut pas vraiment le faire en C), ce qui rend certains algorithmes beaucoup plus facile.
Réponse courte? Parfois.
Techniquement chaque abstraction a un coût, et un langage de programmation est une abstraction de la façon dont le PROCESSEUR fonctionne. C est cependant très proche. Il y a des années, je me souviens de rire à haute voix quand je me suis connecté sur mon compte UNIX et le suivant fortune message (lorsque de telles choses étaient populaires):
C'est drôle parce que c'est vrai: C est le portable de l'assemblée de la langue.
Il est intéressant de noter que l'assemblée de la langue tout fonctionne cependant vous l'écrivez. Il y a cependant un compilateur entre le C et l'assembleur qu'il génère et qui est extrêmement important parce que la rapidité de votre code C est a beaucoup à voir avec la qualité de votre compilateur.
Lors de la gcc est venu sur la scène l'une des choses qui l'ont rendu si populaire est qu'il est souvent beaucoup mieux que les compilateurs C livré avec de nombreux UNIX commercial de saveurs. Non seulement il était en C ANSI (rien de ce K&R C de la foutaise), a été plus robuste et plus généralement produites mieux (plus rapide) du code. Pas toujours, mais souvent.
Je vous dis tout cela car il n'y a pas de couverture de la règle sur la vitesse de C et de l'assembleur, car il n'y a pas de norme objective pour C.
De même, assembleur varie beaucoup en fonction de ce processeur que vous utilisez, votre système spec, ce jeu d'instructions que vous utilisez et ainsi de suite. Historiquement, il y en a eu deux de l'architecture du PROCESSEUR familles: CISC et RISC. Le plus gros joueur dans le CDCI a été et est encore l'architecture Intel x86 (et du jeu d'instructions). RISC dominé le monde UNIX (MIPS6000, Alpha, Sparc et ainsi de suite). Le SCRC a remporté la bataille pour les cœurs et les esprits.
De toute façon, la sagesse populaire quand j'étais un jeune développeur qui a été écrit à la main x86 pourrait souvent être beaucoup plus rapide que C parce que la façon dont l'architecture a travaillé, il a une complexité qui a bénéficié d'un homme de le faire. RISC, d'autre part semblait conçu pour les compilateurs donc noone (je le savais) a écrit le dire assembleur Sparc. Je suis sûr que de telles personnes existaient, mais sans doute qu'ils ont à la fois fou et a été institutionnalisée par maintenant.
Jeux d'instructions sont un point important, même dans la même famille de processeurs. Certains processeurs Intel ont des extensions comme de l'ESS à travers SSE4. AMD avaient leurs propres instructions SIMD. L'avantage d'un langage de programmation comme C était quelqu'un pouvait écrire de sa bibliothèque, de sorte qu'il a été optimisé pour le processeur que vous exécutez sur. C'était dur de travailler en assembleur.
Il y a encore des optimisations que vous pouvez faire en assembleur qu'aucun compilateur pourrait faire et bien écrit en assembleur algoirthm sera aussi vite ou plus vite que C équivalent. La plus grande question est: est-il utile?
Mais à la fin de l'assembleur était un produit de son temps et a été de plus en plus populaire à une époque où les cycles CPU étaient chers. Aujourd'hui, un CPU qui a un coût de $5 à 10 pour la fabrication (Intel Atom) peut faire à peu près tout ce que l'on peut vouloir. La seule vraie raison d'écrire en assembleur ces jours-ci est de faible niveau des choses comme certaines parties d'un système d'exploitation (même si la grande majorité du noyau Linux est écrit en C), pilotes de périphérique, éventuellement, les appareils embarqués (bien que C a tendance à dominer, il y a trop) et ainsi de suite. Ou juste pour le plaisir (ce qui est un peu maso).
Un cas d'utilisation qui peut ne pas s'appliquer, mais plus pour votre nerd plaisir: Sur Amiga, le CPU et la carte graphique/audio puces à se battre pour accéder à une certaine zone de la RAM (la première de 2 mo de RAM pour être précis). Alors, quand vous avez eu seulement 2 MO de RAM (ou moins), l'affichage de graphiques complexes en plus de la lecture audio de tuer les performances de l'UC.
En assembleur, vous pouvez intercaler votre code de telle manière habile que le CPU serait seulement essayer d'accéder à la mémoire vive lorsque la carte graphique/audio puces ont été occupés en interne (c'est à dire quand le bus est gratuit). Donc, par la réorganisation de vos instructions, l'utilisation intelligente du cache du PROCESSEUR, le bus timing, vous pouvez obtenir certains effets qui n'étaient tout simplement pas possible à l'aide de tout langage de plus haut niveau parce que vous aviez à l'heure à chaque commande, même insérer des Opr ici et là pour garder les diverses jetons de chacun radar.
Qui est une autre raison pour laquelle le NOP (No Operation: ne rien faire) l'instruction de la CPU pouvez réellement faire de votre ensemble de l'application de courir plus vite.
[EDIT] bien sûr, la technique dépend d'un matériel spécifique de l'installation. Qui était la principale raison pour laquelle beaucoup de jeux Amiga ne pouvait pas faire face avec des Processeurs plus rapides: Le calendrier de la notice était à l'arrêt.
Point qui n'est pas la réponse.
Même si vous n'avez jamais un programme, que je trouve très utile de connaître au moins une instruction assembleur ensemble. Cela fait partie de l'programmeurs quête sans fin pour en savoir plus et donc être mieux. Également utile lorsqu'il d'entrer dans les cadres de vous n'avez pas le code source, et d'avoir au moins une idée approximative de ce qui se passe. Il vous aide également à comprendre JavaByteCode et .Net IL comme ils sont à la fois semblables à de l'assembleur.
Pour répondre à la question quand vous avez une petite quantité de code ou une grande quantité de temps. Le plus utile pour une utilisation dans des puces intégrées, où de faibles puce de la complexité et de la faible concurrence dans les compilateurs de ciblage de ces puces peuvent faire pencher la balance en faveur de l'homme. Aussi les restrictions sur les périphériques vous êtes souvent en échange de la taille du code/taille de la mémoire/la performance d'une manière qui serait difficile de demander à un compilateur de le faire. par exemple, je sais que cette action de l'utilisateur ne s'appelle pas souvent, je vais avoir des petits de la taille du code et de la mauvaise performance, mais cette autre fonction similaire est utilisé à chaque seconde, je vais avoir une plus grande taille de code et des performances plus rapides. C'est le genre de compromis un métier de l'assemblée programmeur peut utiliser.
Je tiens aussi à ajouter, il y a beaucoup de moyen-sol où vous pouvez coder en C compiler et examiner l'Assemblage du produit, alors, soit vous changer de code C ou modifier et maintenir de l'assemblée.
Mon ami travaille sur des micro-contrôleurs, actuellement jetons pour le contrôle de petits moteurs électriques. Il travaille dans la combinaison d'un faible niveau c et de l'Assemblée. Il m'a dit une fois d'une bonne journée de travail où il réduit la boucle principale de 48 instructions à 43. Il est également confronté à des choix comme le code a grandi pour remplir la 256k de la puce et de l'entreprise est de vouloir une nouvelle fonctionnalité, ne vous
Je voudrais ajouter en tant que développeur avec un portefeuille ou les langues, les plates-formes, les types d'applications que j'ai jamais ressenti le besoin de plonger dans l'écriture de l'assemblée. J'ai aussi toujours apprécié les connaissances que j'ai acquises à ce sujet. Et parfois débogué en elle.
Je sais que j'ai beaucoup plus répondu à la question "pourquoi devrais-je apprendre l'assembleur" mais je trouve que c'est une question plus importante et puis, quand est-ce plus rapide.
permet donc d'essayer une fois de plus
Vous devez être penser à propos de l'assemblage
N'oubliez pas de comparer votre assemblée, généré par le compilateur pour voir qui est plus rapide/petit/meilleur.
David.
sbi
etcbi
) que les compilateurs utilisés (et parfois toujours) ne pas profiter de tout, en raison de leur connaissance limitée du matériel.Je suis surpris que personne n'a dit cela. Le
strlen()
fonction est beaucoup plus rapide s'il est écrit dans l'assemblée! En C, la meilleure chose que vous pouvez faire est detandis que dans l'assemblée, vous pouvez l'accélérer considérablement:
la longueur est dans ecx. Cela se compare à 4 caractères à la fois, il est donc 4 fois plus rapide. Et de penser à l'aide de son mot de eax et ebx, il deviendra 8 fois plus rapide que la précédente routine C!
(word & 0xFEFEFEFF) & (~word + 0x80808080)
est nul ssi tous les octets dans word sont non nuls.Matrice opérations à l'aide d'instructions SIMD est probablement plus rapidement que généré par le compilateur de code.
Je ne peux pas donner des exemples précis, car il était trop il y a plusieurs années, mais il y avait beaucoup de cas où écrite à la main à l'assembleur pourraient effectuer un compilateur. Pourquoi:
Vous pourrait s'écarter de conventions d'appel, le passage d'arguments dans les registres.
Vous pourriez examiner soigneusement comment utiliser les registres, et d'éviter de stocker des variables en mémoire.
Pour des choses comme sauter les tables, vous pourriez éviter d'avoir de limites-vérifier l'index.
Fondamentalement, les compilateurs font un très bon travail d'optimisation, et c'est presque toujours "assez bon", mais dans certaines situations (comme les images de rendu) où vous payez cher pour chaque cycle, vous pouvez prendre des raccourcis parce que vous connaissez le code, où un compilateur n'a pas pu parce qu'il a à être sur le côté sécuritaire.
En fait, j'ai entendu parler d'un rendu graphique de code où une routine, comme une ligne de tirage ou de polygone de remplissage de routine, effectivement généré un petit bloc de code machine sur la pile et exécuté il y, de manière à éviter continu de prise de décision à propos de la ligne de style, la largeur, le modèle, etc.
Cela dit, ce que je veux d'un compilateur à faire est de générer un bon code assembleur pour moi, mais ne pas être trop intelligent, et souvent ils le faire. En fait, une des choses que je déteste au sujet de Fortran est son brouiller le code dans une tentative pour "optimiser", généralement, à aucun but.
Généralement, lorsque les applications ont des problèmes de performances, il est dû à un gaspillage de conception. Ces jours-ci, je ne recommanderais jamais assembleur pour la performance, à moins que l'ensemble de l'application avait déjà été à l'écoute au sein d'un pouce de sa vie, n'était pas encore assez rapide, et passait tout son temps dans serré boucles internes.
Ajouté: j'ai vu beaucoup d'applications écrites en langage d'assemblage, et le principal avantage de vitesse sur un langage comme C, Pascal, Fortran, etc. parce que le programmeur a été beaucoup plus prudent lors du codage en assembleur. Il ou elle va écrire à peu près 100 lignes de code par jour, indépendamment de la langue, et dans un compilateur de langage qui va à l'égalité de 3 ou 400 instructions.
Quelques exemples de mon expérience:
Accès à des instructions qui ne sont pas accessibles à partir de C. Par exemple, de nombreuses architectures (comme le x86-64, IA-64, DEC Alpha, et MIPS 64 bits ou PowerPC) de support d'une version 64 bits de 64 bits de multiplication de la production de 128 bits résultat. GCC a récemment ajouté une extension offrant l'accès à de telles instructions, mais avant que l'assemblée a été nécessaire. Et l'accès à cette instruction peut faire une énorme différence sur les Cpu 64 bits lors de la mise en œuvre de quelque chose comme RSA - parfois autant qu'un facteur de 4 amélioration de la performance.
L'accès à l'UC-des indicateurs spécifiques. Celui qui a mordu m'a beaucoup est le porte drapeau; lorsque l'on fait un multiple de précision plus, si vous n'avez pas accès à l'UC bit on doit au lieu de comparer le résultat pour voir si il a débordé, qui prend de 3 à 5 plus d'instructions par membre; et pire, qui sont tout à fait en série en termes d'accès de données, ce qui tue les performances modernes superscalar processeurs. Lors du traitement de milliers de ces entiers dans une rangée, être capable d'utiliser addc est une grande victoire (il y a superscalar des problèmes avec la contention sur le bit de retenue, mais les Processeurs modernes traiter assez bien avec elle).
SIMD. Même autovectorizing compilateurs ne peut que faire des cas relativement simples, donc si vous voulez une bonne SIMD de performance, il est malheureusement souvent nécessaire d'écrire directement le code. Bien sûr, vous pouvez utiliser intrinsèques au lieu de l'assemblée, mais une fois que vous êtes à la intrinsèques niveau, vous êtes essentiellement la rédaction de l'assemblée de toute façon, juste en utilisant le compilateur comme un allocateur de registres et (théoriquement) l'instruction du planificateur. (J'ai tendance à utiliser intrinsèques pour SIMD tout simplement parce que le compilateur peut générer de la fonction prologues et autres joyeusetés pour moi, donc je peux utiliser le même code sur Linux, OS X et Windows, sans avoir à traiter avec ABI questions comme les conventions d'appel de fonction, mais d'autres que l'ESS intrinsèques ne sont pas vraiment très agréable - l'Altivec semblent mieux si je n'ai pas beaucoup d'expérience avec eux). Comme exemples de choses (jour) de la vectorisation de compilateur ne peut pas comprendre, lire à ce sujet bitslicing AES ou SIMD de correction d'erreur -, on pourrait imaginer un compilateur qui pourrait analyser des algorithmes et de générer du code, mais il se sent à moi comme un smart compilateur est d'au moins 30 ans de l'existence (au mieux).
D'autre part, multicœur des machines et des systèmes distribués ont changé, beaucoup des plus grandes performances de victoires dans l'autre sens - obtenir un supplément de 20% de l'accélération de la rédaction de votre boucles internes de l'assemblée, ou de 300% en l'exécutant à travers de nombreux cœurs, ou 10000% par de les exécuter sur un cluster de machines. Et de cours de haut niveau optimisations (des choses comme les contrats à terme, memoization, etc) sont souvent beaucoup plus facile à faire dans un langage de plus haut niveau comme ML ou Scala de C ou asm, et peuvent souvent fournir une beaucoup plus grande performance de gagner. Alors, comme toujours, il y a des compromis à être fait.
Boucles serrées, comme lors de la lecture avec des images, car une image peut cosist de millions de pixels. S'asseoir et de comprendre comment utiliser au mieux le nombre limité de registres du processeur peut faire une différence. Voici une durée de vie réelle de l'échantillon:
http://danbystrom.se/2008/12/22/optimizing-away-ii/
Alors, souvent, les transformateurs ont certains ésotérique instructions qui sont trop spécialisés pour un compilateur de s'embêter avec, mais à l'occasion d'un assembleur programmateur peut en faire un bon usage. Prendre la XLAT instruction par exemple. Vraiment génial si vous avez besoin de faire table look-up dans une boucle et la table est limité à 256 octets!
À jour le: Oh, venez à penser de ce qui est le plus crucial quand nous parlons de boucles en général: le compilateur a souvent aucune idée sur le nombre d'itérations qui sera le cas le plus courant! Seul le programmeur sait qu'une boucle sera répété de NOMBREUSES fois et que, par conséquent, sera bénéfique pour préparer la boucle avec un travail supplémentaire, ou si il va être réitéré si peu de temps que le set-up seront effectivement prendre plus de temps que les itérations prévu.
Plus souvent que vous ne le pensez, C doit faire des choses qui semblent être inutile à partir d'un Assembly point de vue du programmeur, juste parce que les normes C dire.
Entier de promotion, par exemple. Si vous souhaitez modifier une variable char en C, attendez que le code ne fait juste que, un simple décalage de bits.
Les normes, toutefois, d'appliquer le compilateur de faire un signe étendre à l'int avant la maj et de tronquer le résultat de char par la suite ce qui risque de compliquer le code en fonction de la cible du processeur de l'architecture.
Vous ne savez pas vraiment si votre bien-écrit le code C est vraiment rapide si vous n'avez pas regardé le démontage de ce compilateur produit. Plusieurs fois, vous regardez et voir que "bien écrit" est subjective.
Il n'est donc pas nécessaire d'écrire en assembleur pour obtenir la plus rapide de code jamais, mais il vaut certainement la peine de savoir assembleur pour la même raison.
Je pense que le cas général, lorsque l'assembleur est plus rapide, c'est quand une smart assemblée programmeur regarde le compilateur de la sortie et lui dit: "c'est un chemin critique pour la performance et la je peux écrire ceci pour être plus efficace", et alors que personne réglages que l'assembleur ou réécrit à partir de zéro.
Tout dépend de votre charge de travail.
Pour la journée-à-jour des opérations, le C et le C++ sont très bien, mais il y a certaines charges de travail (toutes les transformations impliquant vidéo (compression, décompression, effets d'image, etc)) c'est à peu près exiger de l'assemblée pour être performant.
Ils impliquent l'utilisation de l'UC spécifiques chipset extensions (MME/MMX/SSE/whatever) qui sont à l'écoute de ce genre d'opération.
J'ai une opération de transposition de bits qui doit être fait, sur 192 ou 256 bits, chaque interruption, ce qui se passe tous les 50 microsecondes.
Il arrive par un fixe carte(contraintes matérielles). À l'aide de C, il a fallu environ 10 microsecondes à faire. Quand j'ai traduit ce à Assembler, en prenant en compte les caractéristiques spécifiques de cette carte, registre spécifique de la mise en cache, et à l'aide de bits opérations orientées; il a fallu moins de 3.5 microseconde à effectuer.
J'ai lu toutes les réponses (plus de 30) et de ne pas trouver une raison simple: l'assembleur est plus rapide que C si vous avez lu et pratiqué la Intel® 64 et IA-32 Optimisation des Architectures Manuel, donc la raison pour laquelle assemblée peut être plus lente, c'est que les gens qui écrivent de telles ralentissement de l'assemblée n'a pas lu le Manuel d'Optimisation.
Dans le bon vieux temps de Intel 80286, chaque instruction est exécutée à un certain nombre de cycles CPU, mais depuis le Pentium Pro, sorti en 1995, les processeurs Intel est devenu superscalar, en utilisant des Complexes Pipelining: de l'Exécution & Enregistrer un nouveau nom. Avant que, sur le Pentium, produite de 1993, il y avait U et V pipelines: double pipe lines qui pourraient s'exécuter deux instructions simples à un seul cycle d'horloge s'ils ne dépendent pas l'un de l'autre; mais ce n'était rien à comparer de ce qui est Hors-de-l'Exécution des ordres & Enregistrer le Renommage est apparu dans le Pentium Pro, et presque laissé inchangées de nos jours.
À expliquer en quelques mots, le plus rapide de code est l'endroit où les instructions ne dépendent pas des résultats précédents, par exemple, vous devez toujours effacer l'ensemble des registres (par movzx) ou de l'utilisation
add rax, 1
au lieu ouinc rax
à supprimer la dépendance de l'état précédent de drapeaux, etc.Vous pouvez en lire plus sur de l'Exécution & Registre de Renommer si le temps le permet, il ya beaucoup d'informations disponibles dans l'Internet.
Il y a également d'autres questions importantes comme la direction de la prévision, le nombre de charger et stocker des unités, nombre de portes qui exécutent des micro-ops, etc, mais la chose la plus importante à considérer est de savoir l'Ordre d'Exécution.
La plupart des gens ne sont tout simplement pas au courant au sujet de l'Exécution de la Commande, de sorte qu'ils écrivent leur assemblée des programmes comme pour 80286, s'attendant à leur instruction va prendre un temps fixe pour exécuter indépendamment de leur contexte; tandis que les compilateurs C sont conscients de l'Exécution de la Commande et de générer le code correctement. C'est pourquoi le code de ces gens ignorent est plus lent, mais si vous devenez conscient, votre code sera plus rapide.
Il pourrait être intéressant de regarder L'optimisation de Immuable et la Pureté par Walter Bright ce n'est pas un profilé de test, mais vous montre un bon exemple de la différence entre manuscrite et généré par le compilateur ASM. Walter Bright écrit optimisation des compilateurs de sorte qu'il pourrait être intéressant de regarder ses autres posts.
LInux assemblée howto, pose la question et donne les avantages et les inconvénients de l'utilisation de l'assemblage.
La réponse la plus simple... et Celui qui sait assemblée bien (aka a la référence à côté de lui, et est en train de profiter de chaque petit cache du processeur et du pipeline de fonction, etc) est garanti pour être capable de produire beaucoup plus rapide que le code tout compilateur.
Cependant, la différence de ces jours-là, n'a pas d'importance dans l'application typique.
L'un des posibilités pour le CP/M-86 version de PolyPascal (frère de Turbo Pascal) pour remplacer le "utilisez-bios-de-sortie-les caractères à l'écran" installation avec un langage machine routine qui dans essense a été donné le x, et y, et la chaîne à y mettre.
Cela a permis de mettre à jour l'écran beaucoup, beaucoup plus vite qu'avant!
Il y avait de la place dans le binaire pour intégrer du code machine (quelques centaines d'octets) et il y avait d'autres trucs aussi, il était donc essentiel de restreindre autant que possible.
Il turnes que depuis l'écran était 80x25 les deux coordonnées pourraient s'intégrer dans un octet chacun, de sorte que les deux pourraient s'intégrer dans un deux-octet mot. Cela a permis de faire les calculs nécessaires en moins d'octets depuis une simple pourrait manipuler les deux valeurs simultanément.
À ma connaissance, il n'existe pas de compilateurs C qui peut fusionner plusieurs valeurs dans un registre, ne instructions SIMD sur eux et de les diviser de nouveau plus tard (et je ne pense pas que la machine des instructions seront plus courtes de toute façon).
L'un des plus célèbres extraits de l'assemblée est de Michael Abrash de mappage de texture boucle (expained en détail ici):
Aujourd'hui, la plupart des compilateurs express advanced CPU instructions spécifiques comme intrinsèques, c'est à dire, les fonctions qui compilé vers le bas à l'instruction elle-même. MS Visual C++ prend en charge intrinsèques MMX, SSE, SSE2, SSE3, et SSE4, si vous avez moins se soucier de descendre à l'assemblée de prendre avantage de la plate-forme d'instructions spécifiques. Visual C++ peut également profiter de la véritable architecture vous cibler avec le /ARCH réglage.
Le droit programmeur, des programmes en Assembleur peut toujours être effectuée plus rapidement que leurs C homologues (au moins un peu). Il serait difficile de créer un programme en C où vous ne pourriez pas prendre au moins une instruction de l'Assembleur.
http://cr.yp.to/qhasm.html a de nombreux exemples.
gcc est devenu largement utilisé compilateur. Ses optimisations ne sont en général pas très bon. Beaucoup mieux que la moyenne programmeur écrit en assembleur, mais pour la performance réelle, pas bon. Il existe des compilateurs qui sont tout simplement incroyable dans le code qu'ils produisent. Donc, comme une réponse générale, il va y avoir beaucoup d'endroits où vous pouvez aller dans la sortie du compilateur et de l'ajuster l'assembleur pour la performance, et/ou tout simplement ré-écrire la routine à partir de zéro.
Longpoke, il y a une seule limitation: le temps. Lorsque vous n'avez pas les ressources pour optimiser chaque changement de code et de dépenser votre temps à l'allocation de registres, d'optimiser quelques déversements de loin et ce n'est pas, le compilateur va gagner à chaque fois. Vous faites votre modification du code, le recompiler et à mesure. Répétez l'opération si nécessaire.
Aussi, vous pouvez faire beaucoup de choses dans les parallèles de haut niveau. Aussi, l'inspection de l'assemblage qui en résulte peut donner l'IMPRESSION que le code est de la merde, mais dans la pratique, il va courir plus vite que ce que vous pensez serait plus rapide. Exemple:
int y = data[i];
//faire des trucs ici..
call_function(y, ...);
Le compilateur va lire les données, de le pousser à pile (noire) et plus tard de lire à partir de la pile et de la passer en argument. Les sons de merde? Il pourrait effectivement être très efficace de compensation de la latence et la plus rapide d'exécution.
//version optimisée
call_function(data[i], ...); //pas de manière optimisée après tout..
L'idée avec la version optimisée a été, que nous avons réduit registre de la pression et éviter de la renverser. Mais en vérité, la "merde" version a été plus rapide!
Regarder le code assembleur, simplement en regardant les instructions et de conclure: plus d'instructions, plus lent, ce serait une erreur de jugement.
La chose ici faire attention: de nombreux assemblée des experts pense ils savent beaucoup de choses, mais en savons très peu. Le changement des règles de l'architecture, à la prochaine, trop. Il n'y a pas d'argent-puce x86 code, par exemple, qui est toujours le plus rapide. Ces jours-ci est mieux de passer par des règles empiriques:
Aussi, faire confiance trop dans le compilateur comme par magie le transformant mal pensé code C/C++ dans "théoriquement optimale de code" est un vœu pieux. Vous devez savoir que le compilateur et l'outil de la chaîne que vous utilisez si vous vous souciez de la "performance" à ce faible niveau.
Les compilateurs C/C++ ne sont généralement pas très bon à la réorganisation des sous-expressions parce que les fonctions ont des effets secondaires, pour commencer. Les langages fonctionnels ne souffrent pas de cette mise en garde mais ne correspondent pas au courant de l'écosystème que bien. Il y a des options du compilateur pour permettre détendue précision des règles qui permettent ordre des opérations à être changé par le compilateur/linker/générateur de code.
Ce sujet est un peu d'une impasse; pour la plupart, il n'est pas pertinent, et le reste, ils savent ce qu'ils font déjà de toute façon.
Tout se résume à ceci: "pour comprendre ce que vous faites", c'est un peu différent de savoir ce que vous faites.
La question est un peu trompeur. La réponse est là, dans votre post lui-même. Il est toujours possible d'écrire assemblée solution pour un problème particulier qui exécute plus rapidement que n'importe quel généré par un compilateur. La chose est que vous devez être un expert en assemblage de surmonter les limites d'un compilateur.
Une expérience assemblée programmeur peut écrire des programmes dans toutes les HLL qui effectue plus rapidement que celui écrit par un inexpérimenté. La vérité est que vous pouvez toujours écrire assemblée des programmes d'exécution plus rapide que celui généré par un compilateur.
Comment sur la création de code machine au moment de l'exécution?
Mon frère une fois (environ 2000) a réalisé une très rapide en temps réel ray-traceur en générant le code au moment de l'exécution. Je ne me souviens pas des détails, mais il y avait une sorte de module principal qui était de boucler à travers des objets, alors qu'il était en train de préparer et d'exécuter un code machine qui est spécifique à chaque objet.
Cependant, au fil du temps, cette méthode a été outruled par nouveau matériel graphique, et il est devenu inutile.
Aujourd'hui, je pense que peut-être certaines opérations sur de grands volumes de données (plusieurs millions d'enregistrements) comme les tableaux croisés dynamiques, de forage, des calculs à la volée, etc. pourrait être optimisée avec cette méthode. La question est: est l'effort en vaut la peine?
C'est très difficile de répondre plus précisément, parce que la question est très imprécise: quel est exactement un "compilateur moderne"?
Pratiquement n'importe quel manuel de l'assembleur d'optimisation pourrait, en théorie, être fait par un compilateur en tant que bien Si c' est fait ne peut pas être dit en général, seulement une version spécifique d'un compilateur spécifique. De nombreux probablement besoin d'autant d'efforts pour déterminer si elles peuvent être appliquées sans effets secondaires dans un contexte particulier que les rédacteurs de compilateur ne vous embêtez pas avec eux.
Dans les jours où la vitesse du processeur a été mesurée en MHz et la taille de l'écran a été en dessous de 1 mégapixels, une astuce pour avoir un affichage plus rapide était de dérouler les boucles: opération d'écriture pour chaque ligne de balayage de l'écran. D'éviter la surcharge de gestion d'un indice de boucle! Couplé avec la détection de rafraîchissement de l'écran, il était très efficace.
C'est quelque chose d'un compilateur C de ne pas le faire... (bien que souvent vous pouvez choisir entre l'optimisation de la vitesse ou pour la taille, je suppose que le premier utilise certains des astuces similaires.)
Je sais que certaines personnes aiment écrire des applications Windows en langage d'assemblage. Ils prétendent qu'ils sont plus rapide (difficile à prouver) et les petits (en effet!).
Evidemment, tant que c'est amusant à faire, il est probablement temps perdu (sauf pour objectif d'apprentissage, bien sûr!), en particulier pour les opérations d'interface utilisateur graphique...
Maintenant, peut-être que certaines opérations, comme à la recherche d'une chaîne dans un fichier, qui peut être optimisée par l'soigneusement écrit le code d'assemblée.
clang
nigcc
vraiment l'obtenir ici: le jamais déroulez le comportement est un peu extrême: beaucoup de simples boucles avec un 1 ou 2 de l'instruction, "charge", serait vraiment aidé par un 2x ou 4x dérouler. clang sur l'autre main est fine complètement dérouler cette boucle avec 2175 itérations en ~200 instructions explicites que, probablement, gonfle la fonction à près de 2K octets. En général, les compilateurs semblent utiliser assez simple heuristiques pour le déroulage qui entraînent souvent des résultats sous-optimaux.En fait, vous pouvez construire à grande échelle des programmes dans un grand modèle de mode segaments peut être limitée à 64 ko de code, mais vous pouvez écrire beaucoup de segaments, les gens donnent l'argument contre l'ASM comme c'est un vieux de la langue et nous n'avons pas besoin de préserver la mémoire, plus que Si c'était le cas, pourquoi serions-nous faire nos PC avec la mémoire, le seul Défaut que je peux trouver avec l'ASM, c'est qu'il est plus ou moins le Processeur de base de sorte que la plupart des programmes écrits pour l'architecture intel n'aurait probablement pas fonctionner sur Une Architecture AMD. Comme pour C étant plus rapide que l'ASM n'est pas de langue plus vite que l'ASM et l'ASM peut faire beaucoup de chose, C et autres HLL ne peut pas le faire au niveau processeur. L'ASM est une langue difficile à apprendre, mais une fois que vous apprendre qu'il n'HLL peut traduire mieux que vous. Si seulement vous pouviez voir certaines des choses HLL de Faire pour vous de code, et de comprendre ce qu'il fait, vous vous demandez pourquoi Plus de gens ne pas utiliser de l'ASM et pourquoi assembers sont plus mis à jour ( Pour un usage grand public de toute façon). Donc non C est pas plus rapide que l'ASM. Même les expériences les programmeurs en C++ utilisent encore et écrire des Morceaux de code en ASM ajoutée de code C++ pour la vitesse. D'autres Langues Aussi que certaines personnes pensent sont obsolètes ou, éventuellement, aucun bien n'est qu'un mythe à la fois par exemple Photoshop est écrit en Pascal/ASM 1ère version de la source a été soumis à la technique du musée d'histoire, et paintshop pro est écrit encore écrit en Python,TCL et à l'ASM ... un dénominateur commun de ces "Fast et la Grande processeurs d'image est l'ASM, bien que photoshop est passé à delphes maintenant il est encore pascal. et tout des problèmes de vitesse sont à venir de pascal, mais c'est parce que nous aimons la façon dont les programmes look et pas ce qu'ils font maintenant des jours. Je voudrais faire un Clone de Photoshop dans le plus pur ASM qui j'ai travaillé sur les et ses à venir le long plutôt bien. pas de code,d'interpréter,de arange,rewwrite,etc.... Juste le code et allez processus complet.
Je dirais que quand vous êtes mieux que le compilateur pour un ensemble donné d'instructions. Donc pas de réponse générique, je pense que
De nos jours, compte tenu de ces compilateurs Intel C++ qui extrêmement optimisation de code C, il est très difficile de rivaliser avec les compilateurs de sortie.
Cette question est un peu inutile, parce que de toute façon c est compilé en assembleur.
Mais, l'assembleur produit par l'optimisation des compilateurs est presque entièrement optimisé, de sorte que si vous n'avez vingt doctorat sur l'optimisation de montage spécifique, vous ne pouvez pas battre le compilateur.
J'ai l'habitude de travailler avec quelqu'un qui a dit "si le compilateur est con pour comprendre ce que vous êtes en train de faire et ne peut pas optimiser, votre compilateur est cassé et qu'il est temps pour obtenir un nouveau". Je suis sûr qu'il y a des cas limites lors de l'assemblée battre votre code en C, mais si vous souvent de trouver vous-même à l'aide d'assembler de "gagner" sur votre compilateur, votre compilateur est en panne.
Même chose peut être dite pour l'écriture de "optimisé" SQL qui tente de forcer le planificateur de requête à faire des choses. Si vous vous retrouvez à ré-organiser les requêtes pour obtenir le planificateur de faire ce que vous voulez, votre planificateur de requête est en panne--en obtenir un nouveau.