Est-il nécessaire de comprendre ce qui se passe au niveau matériel pour être un bon programmeur?

24

Je suis un programmeur autodidacte, juste au cas où cette question trouverait une réponse dans CS 101. J'ai appris et utilisé beaucoup de langues, principalement pour mon usage personnel, mais parfois pour des choses professionnelles.

Il semble que je rencontre toujours le même mur lorsque je rencontre des problèmes de programmation. Par exemple, je viens de poser une question sur un autre forum sur la façon de gérer un pointeur vers un tableau renvoyé par une fonction. Au départ, je pense que je ne connais tout simplement pas la technique appropriée que les concepteurs de C ++ ont mise en place pour gérer la situation. Mais à partir des réponses et des discussions qui suivent, je vois que je ne comprends pas vraiment ce qui se passe quand quelque chose est «retourné».

Jusqu'à quel niveau de compréhension du processus de programmation un bon programmeur doit-il atteindre?

bev
la source
3
Mon conseil: apprenez un assemblage x86 (DOS ou autre). Apprenez ensuite à lire une partie de la sortie de l'assembleur de quelques petits morceaux de code C. Posez des questions si vous ne comprenez pas le résultat. Répéter. Cela vous obligera à comprendre ce qui se passe au niveau du processeur
Earlz
Earlz - Voulez-vous dire que je devrais apprendre à programmer en utilisant le jeu d'instructions x86? Est-ce le «niveau CPU»?
bev
Job - merci, c'était amusant. Il a en fait fait quelques erreurs, mais juste pour info.
bev

Réponses:

33

Non, personne ne comprend ce qui se passe au niveau matériel.

Les systèmes informatiques sont comme des oignons - il existe de nombreuses couches, et chacune dépend de la couche en dessous pour le support. Si vous êtes le gars qui travaille sur l'une des couches externes, vous ne devriez pas trop vous soucier de ce qui se passe au milieu de l'oignon. Et c'est une bonne chose, car le milieu de l'oignon change toujours. Tant que le ou les calques qui prennent en charge votre calque particulier restent identiques et prennent en charge votre calque, vous êtes bon.

Mais encore une fois...

Oui. Je veux dire, vous n'avez pas besoin de comprendre ce qui se passe vraiment à l'intérieur de l'oignon, mais cela aide beaucoup d'avoir un modèle mental de ce à quoi ressemble l'intérieur d'un oignon typique. Peut-être pas la partie la plus profonde, où vous avez des portes composées de transistors et autres, ou la couche suivante ou deux, où vous avez un microcode, une horloge, des unités de décodage d'instructions, etc. Les couches suivantes, cependant, sont là où vous 'ai des registres, la pile et le tas. Ce sont les couches les plus profondes où vous avez beaucoup d'influence sur ce qui se passe - le compilateur traduit votre code en instructions qui s'exécutent à ce niveau, et si vous le souhaitez, vous pouvez généralement parcourir ces instructions et découvrir ce qui se passe "vraiment".

La plupart des programmeurs expérimentés ont une version légèrement féerique de ces couches dans leur tête. Ils vous aident à comprendre de quoi parle le compilateur lorsqu'il vous indique qu'il y a eu une "exception d'adresse non valide" ou une "erreur de débordement de pile" ou quelque chose du genre.

Si vous êtes intéressé, lisez un livre sur l'architecture informatique. Il n'a même pas besoin d'être un livre particulièrement nouveau - les ordinateurs numériques fonctionnent à peu près de la même manière depuis longtemps. Plus vous en apprendrez sur l'intérieur de l'oignon, plus vous serez étonné que tout cela fonctionne! Apprendre (approximativement) ce qui se passe dans les couches inférieures rend la programmation à la fois moins mystérieuse et, en quelque sorte, plus magique. Et vraiment, plus amusant.

Une autre chose que vous pourriez examiner est les oignons incorporés. Euh, je veux dire des systèmes embarqués. Il existe un certain nombre de plates-formes intégrées assez faciles à utiliser: Arduino et BASIC Stamp en sont deux exemples. Ce sont essentiellement de petits microprocesseurs avec de nombreuses fonctionnalités intégrées. Vous pouvez les considérer comme des oignons avec moins de couches que votre ordinateur de bureau typique, il est donc possible d'avoir une compréhension assez approfondie de ce qui se passe dans l'ensemble du système, du matériel au logiciel.

Caleb
la source
2
Merci. Cela répond essentiellement à ma question. Je suis un EE qui a conçu des registres, des additionneurs, des multiplexeurs, etc. au niveau de la puce (c'est-à-dire au niveau des transistors), donc j'obtiens le niveau le plus bas (sauf si nous parlons de mécanique quantique). Je peux également utiliser les langues que je connais assez bien. J'ai juste un énorme écart au niveau intermédiaire (pile, tas), où vous dites que le compilateur fait son travail. Puisque, comme vous le dites, je veux que mon expérience de programmation soit "moins mystérieuse et, ..., plus magique". il semble que je devrais étudier les niveaux qui me sont encore inconnus.
bev
@bev: Dans ce cas, vous devriez vraiment vérifier une plate-forme comme Arduino.
Caleb
désolé d'être ennuyeux, mais j'ai vérifié Arduino, et je ne vois pas vraiment comment son utilisation m'aiderait à comprendre comment un compilateur traite les pointeurs et les tableaux différemment. Qu'est-ce que je ne vois pas?
bev
@bev: Si vous voulez simplement savoir comment les fonctions sont appelées, vous pouvez probablement passer 30 minutes à lire à ce sujet et à faire. Si vous voulez mieux comprendre comment tout fonctionne ensemble, ce sera plus facile avec un petit système. C'est le meilleur moyen de mettre l'oignon entier dans votre tête à la fois. AVR, la famille de puces sur laquelle Arduino est basé, est un système agréable, polyvalent et facile à utiliser avec un jeu d'instructions suffisamment petit pour apprendre sans trop de problèmes.
Caleb
Ah ok. La page d'accueil est un peu trouble sur cet aspect de leurs produits. Je regarderai encore.
bev
10

Vous ne parlez pas du niveau matériel, vous parlez de ce que le compilateur fait vraiment avec ce que vous lui demandez de faire.

Vous avez très certainement besoin de ce niveau de compréhension afin de comprendre ce qui s'est mal passé quand ce n'est pas évident, en particulier lorsqu'il s'agit d'une situation de mémoire stomp.

Loren Pechtel
la source
Loren - Oui! Merci pour la simple vérité. Maintenant, je dois trouver la meilleure façon d'apprendre ce que les compilateurs c ++ font avec leurs types de données. BTW, en tant qu'EE, je sais que ce n'est pas le niveau matériel littéralement. Je ne savais tout simplement pas comment vous, les geeks CS, l'appeliez. (Toujours pas d'ailleurs. Niveau du compilateur?)
bev
BTW - mémoire stomp?
bev
@Bev: Vous venez de prouver mon point de vue ici - si vous ne savez même pas ce qu'est une mémoire stomp, vous aurez beaucoup de mal à trouver un bogue à cause d'un. Un piétinement de mémoire, c'est quand quelque chose écrit à un endroit où il n'est pas censé et efface (piétine) tout ce qui s'y trouvait. Si vous êtes chanceux, tout ce que vous avez touché était immédiatement vital et au moins il explose. Si vous n'avez pas de chance, le programme continue de fonctionner avec quelques trous dans ses données.
Loren Pechtel
Merci pour la clarification. Cela me montre également combien je ne sais pas, car pour autant que je sache, j'écris simplement dans le tas ou la pile, sans contrôle plus fin.
2011 à
@Bev: Le problème survient lorsque vous écrivez dans un endroit que vous ne pensez pas écrire. Vous avez quelque chose sur la pile et vous en faites un pointeur. Vous quittez la routine - l'élément disparaît, pas le pointeur. Maintenant, que se passe-t-il lorsque vous écrivez sur ce pointeur ?? Ou vous avez un tableau de 100 éléments - que se passe-t-il lorsque vous écrivez à l'élément n ° 200?
Loren Pechtel
6

Comprendre la mémoire du programme! = Comprendre le matériel

Comprendre la hiérarchie de la mémoire == Comprendre le matériel


Pour répondre à votre question générique: cela dépend. Cela ne peut pas nuire à la compréhension du matériel, mais le comprendre n'aidera pas dans tous les cas.

Sur la base de votre exemple, il vous suffit de mieux comprendre comment la mémoire est divisée et comment elle est organisée lorsque vous exécutez un programme. Comprendre le matériel ne vous aidera pas à cet égard, car la mémoire (visible par un programme) ne représente même pas vraiment le matériel grâce à la magie de la mémoire virtuelle.

Si vous étiez curieux de connaître les problèmes de performances en fonction de l'ordre dans lequel vous accédez à la mémoire, MAINTENANT, vous bénéficieriez de la compréhension du matériel, de la hiérarchie de la mémoire, des échecs de cache, des défauts de page et de toute la splendeur merveilleuse du matériel.

riwalk
la source
Stargazer - Je ne suis pas encore au point où je peux m'inquiéter des problèmes de performances. Bientôt, je l'espère. Merci pour vos commentaires.
bev
5

Si vous ne décidez d'apprendre un peu d'assembleur, vous devriez probablement apprendre quelque chose comme 6502 assembleur sur un Commodore 64 (émulé, bien sûr), ou 68000 sur un Amiga.

Vous pouvez vous faire une idée du Commodore 64 ici ...

http://thepiratebay.org/torrent/4609238/Tag3-Saal2-Slot16_00--ID2874-the_ultimate_commodore_64_talk-Main

Le livre classique sur tout ce que vous devez savoir est celui décrit ici ...

http://reprog.wordpress.com/2010/03/12/programming-books-part-3-programming-the-commodore-64/

Vous pouvez probablement trouver une analyse PDF si vous regardez autour de vous.

IMO, 6502 est plus facile que Z80, et 68000 est plus facile que 8086 - jeux d'instructions plus réguliers, etc.

Mais le CPU n'est qu'un aspect du matériel. En outre, un processeur moderne est une bête très différente, et il fait des choses qui sont transparentes même du point de vue des compilateurs - comme présenter un espace d'adressage virtuel.

Un avantage particulier du 6502 sur le C64 est que non seulement le processeur est simple, mais il y a aussi du matériel très simple à pirater. J'ai eu beaucoup de plaisir à jouer avec la puce de musique SID.

Donc - c'est probablement un exercice intéressant si vous n'y passez pas trop de temps. J'ai appris l'assembleur 6502 comme deuxième langue quand j'avais environ 14 ans, juste après Commodore Basic. Mais surtout, il s'agit d'obtenir ce modèle de travail très simple afin que vous puissiez y ajouter des idées plus sophistiquées avec un minimum de malentendus.

Quelques choses utiles que vous pouvez apprendre en travaillant dans l'assembleur ...

  • Fonctionnement des registres du processeur.
  • Fonctionnement de l'adressage mémoire, y compris l'indirection.
  • Comment fonctionne la pile CPU.
  • Fonctionnement de la logique au niveau du bit.
  • Comment le CPU contrôle les périphériques d'E / S.
  • Comment fonctionnent les interruptions.

Une raison particulière que je recommanderais est d'avoir une meilleure intuition de la façon dont les étapes simples fonctionnent de manière entièrement déterministe et mécanique et totalement sans intelligence ni bon sens. S'habituer fondamentalement au modèle d'exécution impérative sous sa forme la plus pure et la plus obstinément ignorante.

Précisément comment il est utile de connaître la plupart de ces choses maintenant, cependant, est une question difficile.

Une chose que vous n'apprendrez pas est de bien jouer avec une hiérarchie de mémoire. Ces vieilles machines avaient pour la plupart un modèle de mémoire simple sans couches de cache et sans mémoire virtuelle. Vous n'aurez pas non plus beaucoup d'informations sur la concurrence - ils étaient certainement des moyens de gérer cela, mais cela signifiait principalement des interruptions. Vous n'avez pas besoin de vous soucier des mutex, etc.

Parfois, un modèle mental de la façon dont ces choses fonctionnaient autrefois ou du fonctionnement de l'assembleur peut même induire en erreur. Par exemple, penser à un pointeur C comme une adresse peut conduire à des problèmes de comportement indéfinis. Le pointeur AC est normalement implémenté comme un entier contenant une adresse, mais il n'y a aucune garantie que cela soit strictement vrai. Par exemple, sur certaines plateformes bizarres, différents pointeurs peuvent pointer vers différents espaces d'adressage. Cela devient important lorsque vous voulez faire de l'arithmétique ou de la logique au niveau du bit avec deux pointeurs.

À moins que vous n'ayez une de ces plates-formes bizarres, vous ne pensez peut-être pas que cela vous intéresse - mais les compilateurs de nos jours sont de plus en plus susceptibles d'exploiter un comportement non défini pour l'optimisation.

Un modèle mental de l'architecture du système peut donc être utile, mais il est toujours important de coder en fonction de la spécification de la langue, pas d'un modèle hypothétique que votre langue et votre plate-forme peuvent ne pas respecter.

Enfin, beaucoup de choses utiles sur les modèles mentaux proviennent de la façon dont les compilateurs génèrent du code - et la génération de code pour les langages modernes est très différente des compilateurs assez triviaux disponibles à l'époque.

C'est un de mes livres préférés pour ça ...

http://dickgrune.com/Books/MCD_1st_Edition/

Outre les informations sur l'analyse syntaxique et les AST, etc., il couvre la génération de code pour une gamme de paradigmes de langage - impératif, POO, fonctionnel, logique, parallèle et distribué - et également pour la gestion de la mémoire. Si vous voulez savoir comment fonctionnent les appels de méthodes polymorphes sans vous enliser dans les détails du jeu d'instructions CPU, un livre comme celui-ci est votre ami - et une nouvelle édition devrait bientôt sortir.

Steve314
la source
Steve - wow. Je suis presque sans voix avec l'exhaustivité et la concentration de votre réponse à ma question. Merci beaucoup d'avoir pris le temps d'écrire tout cela. Je prendrai certainement vos suggestions.
bev
1
Je dirais que l'assembleur PDP-11 est un peu plus agréable à apprendre que tous les autres mentionnés. Ce que tous les autres enseignent, ce sont les limitations imposées par des ressources matérielles plus limitées et / ou par une conception matérielle et une réflexion plus limitées. Quelque chose comme l'un de la famille 8051 bien trop courante enseigne à quel point le modèle de programmation peut être bizarre sur un matériel aussi limité (où la mention de Steve de différents espaces d'adressage, par exemple, entre en jeu).
Greg A. Woods,
@Greg - Je n'ai jamais pu jouer avec un PDP-11, je le crains. Ni un 8051 - J'ai fait du travail intégré pendant un certain temps, mais cela utilisait une puce de la famille 8096. Je viens juste de jeter un œil ici - intéressant. J'ai entendu parler de l'architecture de Harvard avant un certain temps, mais je ne savais pas qu'il y avait quelque chose comme ça qui était très populaire et qui est toujours utilisé.
Steve314
4

Il y a vingt ans, c'était important, mais pas tellement maintenant - il y a beaucoup plus de couches d'abstraction entre le logiciel et le matériel moderne.

Il est utile de savoir des choses comme avoir besoin de plusieurs threads pour tirer parti de plusieurs cœurs ou qu'utiliser plus de mémoire qu'il n'en existe sur le système est une mauvaise chose, mais au-delà, vous n'en avez pas vraiment besoin à moins que ce soit votre travail d'écrire ces abstractions couches.

Le reste de votre question suggère que vous pouvez être plus concerné par le compilateur que par le matériel, ce qui est un peu différent. Vous pouvez rencontrer des cas où cela est important, mais ceux-ci ont tendance à être triviaux (la récursion infinie ne fonctionne pas très bien) ou le type de cas marginaux où vous pouvez vous sentir à l'aise pour le résoudre mais ne rencontrerez probablement jamais le même problème encore.

Tom Clarkson
la source
Oui, vous avez raison, je suis plus concerné par le compilateur. Aussi, merci pour votre suggestion à propos de plusieurs threads, plusieurs cœurs, etc. Elle est simplement entrée dans mon fichier de notes toLearn.
bev
@bev multithreading est facile à apprendre, ne le faites pas à moins que vous ne l'ayez vraiment et même alors ne le faites pas. plus de problèmes que sa valeur dans mon expérience.
Skeith
@Skeith - merci pour l'astuce. Je m'en souviendrai.
bev
4

Il aide beaucoup à connaître et comprendre l'abstraction présentée par le matériel, et un peu de l'idée générale sur la façon dont cette illusion est créée - mais en essayant de comprendre vraiment comment le matériel moderne vraiment fonctionne est une énorme quantité de travail à partir de laquelle vous » re ne verra probablement qu'un rendement minimal.

Si vous pardonnez une diversion mineure: cela me rappelle quelque chose que j'ai remarqué il y a quelques années. Il y a des décennies (jusqu'à la fin des années 1970 environ), la plupart des gens pensaient que les ordinateurs étaient à un pas de la magie - à peine affectés par les lois de la physique, capables de toutes sortes de choses qui n'avaient pas vraiment de sens, etc. À l'époque, j'ai passé pas mal de temps à essayer (surtout sans succès) de convaincre les gens que non, ils n'étaient pas magiques. C'étaient vraiment des machines assez ordinaires qui faisaient un nombre limité de choses très rapidement et de manière fiable, mais étaient par ailleurs extrêmement banales.

De nos jours, la vue de la plupart des gens sur les ordinateurs a changé. Ils sont maintenant assez ordinaires - au point que pas mal de gens très ordinaires les comprennent. Par exemple, il y a quelque temps, alors que je dînais, j'ai vu / entendu un serveur et une serveuse pendant leur pause discuter de ce qu'elle devrait obtenir dans son nouvel ordinateur. Les conseils qu'il donnait étaient tout à fait raisonnables et réalistes.

Ma vision des ordinateurs a également changé. Je suis allé à Hot Chips, et avant cela, le Microprocessor Forum remonte au milieu des années 1990. J'en sais probablement plus sur le matériel des microprocesseurs qu'au moins 99% des programmeurs - et sachant ce que je fais, je dirai ceci: ils ne sont plus ordinaires. Ils ne cassent presque les lois de la physique. J'ai fait beaucoup de tests de bas niveau et je peux le dire avec certitude: dépasser l'illusion créée par le CPU et montrer comment le matériel fonctionne vraiment est souvent incroyablement difficile. J'aimerais pouvoir poster une photo de l'une de nos configurations avec un ordinateur enfoui sous les câbles de pas moins de 4 analyseurs logiques juste pour mesurer correctement un aspect du fonctionnement de la mise en cache sur un processeur moderne (sans parler d'une programmation vraiment fastidieuse pour garantir que ce que nous avons mesuré était exactement ce que le processeur faisait, et rien d'autre).

Jerry Coffin
la source
Jerry - merci pour vos commentaires. Étant un EE, je suis plus à l'aise avec le niveau du transistor que certains des niveaux d'abstraction les plus élevés. Je me demande vraiment ce que je dois savoir pour être un bon programmeur C ++.
bev
Cette image semble intéressante. Pourquoi ne pouvez-vous pas l'afficher?
Mason Wheeler
@Bev: Vous n'avez pas vraiment besoin de savoir quoi que ce soit au niveau du transistor pour être un bon programmeur. Ces abstractions sont là pour une raison, et vous pouvez presque toujours considérer que tout ce qui se situe à un niveau d'abstraction inférieur à celui du code / assemblage de la machine est complètement hors de propos et supposez simplement que cela fonctionne.
Mason Wheeler
@MasonWheeler: Je l'ai emmené là où j'avais l'habitude de travailler, mais comme je n'y travaille plus, y accéder serait probablement un peu plus difficile (probablement pas impossible - j'arrête en bons termes, mais quand même. ..)
Jerry Coffin
1

Différentes langues fonctionnent à différents niveaux d'abstraction du matériel. C et C ++ sont de très bas niveau. Les langages de script, d'autre part, nécessitent que vous en sachiez moins sur les détails sous-jacents.

Cependant, je dirais toujours que dans tous les cas, plus vous en savez, mieux vous serez un programmeur. Une partie de la programmation consiste à jongler avec plusieurs niveaux d'abstraction en même temps.

Si vous programmez en C ++, vous devez avoir une assez bonne compréhension du fonctionnement d'un processeur moderne, au moins au niveau d'abstraction auquel le compilateur fonctionne. (Il se passe aussi des choses à l'intérieur du CPU qui sont transparentes pour le compilateur).

Scott Whitlock
la source
Scott - par "une assez bonne compréhension du fonctionnement d'un processeur moderne ...", voulez-vous dire comment fonctionne la logique numérique (par exemple, comment les cartes karnaugh, les tables de vérité et les portes ET / OU / NOR / XOR fonctionnent)? ou voulez-vous dire quelles ressources le compilateur utilise directement (c'est-à-dire les registres)?
bev
En savoir plus, c'est bien. Le vrai truc, cependant, est de savoir quel genre de "plus" vous en donnera le plus pour votre argent. La connaissance des horaires des instructions, par exemple, ne sera pas très utile lorsqu'il est presque impossible de prédire quelles instructions votre compilateur utilisera. Apprendre à utiliser un profileur donnera probablement un bien meilleur rapport coût / bénéfice.
Steve314
1
@bev - Non, je ne pense pas que vous ayez besoin de descendre au niveau de la porte. Si vous connaissiez juste l'architecture de base (mémoire, bus, CPU), comment elle charge une instruction, l'exécute, stocke le résultat, etc., vous êtes probablement OK. Vous devez également comprendre comment le compilateur dispose l'espace mémoire d'un programme, y compris comment il utilise la pile et le tas.
Scott Whitlock
@ScottWhitlock - Merci - c'est juste le genre de recommandations spécifiques que je cherchais.
bev
0

Je voudrais ajouter un point sur la conception globale des langages de niveau supérieur comme C.

En général, je pense qu'il est prudent de dire que de tels langages peuvent être considérés comme implémentant une machine abstraite, et c'est d'ailleurs ainsi que Dennis Ritchie lui-même a décrit le fonctionnement de C et comment la conception particulière de la machine abstraite de C en a fait un langage plus portable. En tant que tel, avoir une certaine compréhension de l'architecture informatique et du fonctionnement au niveau de la machine peut être extrêmement utile pour comprendre également la machine abstraite d'un langage.

L'article de DMR, Portabilité des programmes C et du système UNIX, est le premier dont je me souviens avoir discuté du modèle de machine (abstraite) pour C.

Je pense que l'article de DMR sur l'histoire et le développement de C est également extrêmement utile pour montrer comment le matériel réel affecte la conception du langage, et est peut-être aussi un exemple de conception de langage de programmation précoce: Le développement du langage C

Greg A. Woods
la source
Comme vous êtes nouveau ici, vous semblez penser que c'est un forum, ce n'est certainement pas le cas. Vos réponses à une question ne devraient pas être un point que vous ajoutez, cela devrait être relégué aux commentaires, et la réponse devrait essayer d'être une réponse complète directement à la question. Cela dit, vous faites un bon point et cela est précieux sur les informations sur le sujet, peut-être que si vous pouviez mettre quelques lignes dans cette réponse, la question directement avec cette explication serait formidable. Informations intéressantes que vous partagez ici. Bienvenue aux programmeurs!
Jimmy Hoffa
les commentaires ne sont pas versionnés et ne sont pas permanents, et sont donc inutiles pour ajouter à un ensemble de réponses. La plupart des affiches ont également tendance à ignorer l'utilisation des commentaires pour mettre à jour leurs réponses, et la plupart des réponses ne sont pas marquées comme des réponses "wiki communautaire" et ne peuvent donc pas être modifiées par d'autres de manière à maintenir une certaine attribution au (x) contributeur (s) suivant (s) . En outre, cette question particulière a lancé une véritable discussion, et que cela vous plaise ou non, c'est ainsi que certaines de ces choses se passent. Essayer de forcer chaque contribution dans un moule est un échec majeur du concept stackexchange.
Greg A. Woods
et, entre autres, j'ai effectivement répondu, Albiet implicitement, à la seule vraie question de l'OP: il faut avoir suffisamment de compréhension du matériel pour pouvoir modéliser la machine abstraite au cœur de la conception d'un langage.
Greg A. Woods