La gestion de la mémoire dans la programmation devient-elle une préoccupation non pertinente?
La gestion de la mémoire (ou contrôle) est en fait la principale raison pour laquelle j'utilise C et C ++.
La mémoire est relativement bon marché maintenant.
Pas de mémoire rapide. Nous examinons encore un petit nombre de registres, par exemple un cache de données de 32 Ko pour L1 sur i7, 256 Ko pour L2 et 2 Mo pour L3 / cœur. Cela dit:
Si nous ne parlons pas en termes de plates-formes cibles avec des limites strictes en termes de mémoire de travail (systèmes intégrés, etc.), l'utilisation de la mémoire devrait-elle être une préoccupation lors de la sélection d'un langage généraliste aujourd'hui?
Utilisation de la mémoire à un niveau général, peut-être pas. Je suis un peu peu pratique dans la mesure où je n'aime pas l'idée d'un bloc-notes prenant, par exemple, 50 mégaoctets de DRAM et des centaines de mégaoctets d'espace sur le disque dur, même si j'ai encore beaucoup à faire. Cela fait longtemps que je suis dans le coin et cela me semble bizarre et assez dégoûtant de voir une application aussi simple prendre relativement autant de mémoire pour ce qui devrait être faisable avec des kilo-octets. Cela dit, je pourrais peut-être vivre avec moi-même si je rencontrais une telle chose si elle était toujours agréable et réactive.
La raison pour laquelle la gestion de la mémoire est importante pour moi dans mon domaine n’est pas pour autant réduire l’utilisation de la mémoire en général. L'utilisation de centaines de mégaoctets de mémoire ne ralentira pas nécessairement l'application de manière non triviale si aucune de ces mémoires n'est fréquemment utilisée (par exemple: uniquement en cliquant sur un bouton ou sous une autre forme de saisie utilisateur, ce qui est extrêmement rare, à moins que vous ne le fassiez. parlent de joueurs coréens de Starcraft qui pourraient cliquer sur un bouton un million de fois par seconde).
La raison pour laquelle il est important dans mon domaine est de garder la mémoire serrée et rapprochée (par exemple, une boucle sur chaque image) dans ces chemins critiques. Nous ne voulons pas avoir une mémoire cache manquée chaque fois que nous accédons à un élément sur un million seulement qui doit être accessible en boucle à chaque image. Lorsque nous déplaçons de grandes quantités de mémoire dans la hiérarchie, disons des lignes de cache de 64 octets, il est vraiment utile que ces 64 octets contiennent tous des données pertinentes, si nous pouvons adapter plusieurs éléments de données à ces 64 octets, et si nos modes d'accès sont tels que nous les utilisons tous avant l'expulsion des données.
Les données fréquemment consultées pour le million d’éléments pourraient ne couvrir que 20 mégaoctets, même si nous avons des giga-octets. Il y a toujours un monde de différences dans les taux de trame qui se superposent à chaque donnée tracée si la mémoire est serrée et rapprochée pour minimiser les erreurs de cache, et c’est là que la gestion / le contrôle de la mémoire est si utile. Exemple visuel simple sur une sphère de quelques millions de sommets:
Ce qui précède est en réalité plus lent que ma version mutable car il teste une représentation de structure de données persistante d’un maillage, mais mis à part cela, j’avais du mal à atteindre de telles vitesses de trame même avec la moitié de ces données (certes, le matériel est devenu plus rapide depuis mes difficultés ) parce que je n’ai pas eu l’impression de minimiser les erreurs de cache et l’utilisation de la mémoire pour les données de maillage. Les maillages font partie des structures de données les plus délicates que j'ai traitées à cet égard, car elles stockent une grande quantité de données interdépendantes devant rester synchronisées telles que des polygones, des arêtes, des sommets, autant de cartes de texture que l'utilisateur souhaite attacher, des poids, etc. cartes de couleurs, jeux de sélection, cibles de morphing, poids des arêtes, matériaux polygonaux, etc. etc. etc.
J'ai conçu et mis en œuvre un certain nombre de systèmes de maillage au cours des deux dernières décennies et leur vitesse était souvent très proportionnelle à leur utilisation en mémoire. Même si je travaille avec tellement, beaucoup plus de mémoire que lorsque j'ai commencé, mes nouveaux systèmes de maillage sont 10 fois plus rapides que ma première conception (il y a presque 20 ans) et dans une large mesure car ils utilisent environ 1 / 10ème des années précédentes. la mémoire. La version la plus récente utilise même la compression indexée pour stocker le plus de données possible. Malgré la surcharge de traitement liée à la décompression, la compression a réellement amélioré les performances car, encore une fois, nous avons si peu de mémoire rapide précieuse. Je peux maintenant adapter un million de polygones avec des coordonnées de texture, des plis de bords, des affectations de matériaux, etc., ainsi qu'un index spatial correspondant d'environ 30 mégaoctets.
Voici le prototype modifiable avec plus de 8 millions de quadrangles et un schéma de subdivision multires sur un i3 avec un GF 8400 (datant d’il ya quelques années). C'est plus rapide que ma version immuable mais je ne l'utilise pas en production car j'ai trouvé la version immuable tellement plus facile à maintenir et les performances ne sont pas si mauvaises. Notez que le cadre filaire n'indique pas les facettes, mais les patchs (les fils sont en fait des courbes, sinon tout le maillage serait noir), bien que tous les points d'une facette soient modifiés par le pinceau.
Donc de toute façon, je voulais juste montrer une partie de ce qui précède pour montrer des exemples concrets et des domaines dans lesquels la gestion de la mémoire est si utile et aussi, espérons-le, afin que les gens ne pensent pas que je parle juste de mes fesses. J'ai tendance à être un peu irrité lorsque les gens disent que la mémoire est tellement abondante et bon marché, parce que cela parle de mémoire lente comme la mémoire DRAM et les disques durs. Il est encore si petit et si précieux quand on parle de mémoire rapide, et la performance pour des chemins véritablement critiques (c'est-à-dire, cas commun, pas pour tout) est liée au fait de jouer avec cette petite quantité de mémoire rapide et de l'utiliser aussi efficacement que possible. .
Pour ce genre de choses, il est vraiment utile de travailler avec un langage qui vous permet de concevoir des objets de haut niveau comme le C ++, par exemple, tout en pouvant stocker ces objets dans un ou plusieurs tableaux contigus avec la garantie que la mémoire de tous ces objets seront représentés de manière contiguë et sans surcharge de mémoire inutile par objet (ex: tous les objets ne nécessitent pas de réflexion ou d'envoi virtuel). Lorsque vous vous déplacez dans ces domaines critiques en termes de performances, il devient réellement plus productif de disposer d'un tel contrôle de la mémoire, par exemple en manipulant des pools d'objets et en utilisant des types de données primitifs pour éviter les frais généraux d'objet, les coûts de GC, et de conserver un accès fréquent à la mémoire. ensemble contigu.
Ainsi, la gestion / le contrôle de la mémoire (ou son absence) est en fait une raison dominante dans mon cas pour choisir la langue qui me permet le plus efficacement de résoudre les problèmes. J'écris définitivement ma part de code qui n'est pas critique en termes de performances, et pour cela, j'ai tendance à utiliser Lua, qui est assez facile à intégrer depuis C.