Salut,
je me pose une question pour un développement en cours (réseaux neuronaux) vis à vis de l'optimisation niveau perfs.
Je vais avoir des tableaux de structures avec différents champs. Certains champs contiennent des infos qui typiquement tiennent sur quelques bits, et j'hésite entre deux options:
- utiliser des champs alignés idéalement pour le processeur (32/64 bits)
- compacter en utilisant par exemple des champs de bits
La première option améliore la vitesse d'accès aux informations par le processeur, mais gâche beaucoup de mémoire (un booléen sur 64 bits…).
La seconde permet de gâcher moins de mémoire, donc d'avoir plus d'informations accessibles au niveau des caches - pour un surcoût de décapsulation en lecture (+remise en place des infos plus coûteuse s'il y a des écritures).
Autres critères, certaines infos vont avoir des mises à jour régulières, d'autres ne seront utilisées quasi qu'en lecture.
Quelqu'un a-t-il un retour d'expérience concernant ce genre de choix ?
Merci.
# Teste ?
Posté par solsTiCe (site web personnel) . Évalué à 6.
J'y connais rien mais je me disais que le mieux, c'était que tu testes toi-même.
Tu en es au stage de l'optimisation, et c'est sans doute très lié à ton code donc chercher une réponse générique…
Enfin, je dis ça -> []
# En général
Posté par TheBreton . Évalué à 2.
mais vraiment en général, il est recommandé pour les performances d'utiliser le type natif du processeur.
Si ton proc est 8 bits, utilise de preférence des variables 8 bits (et pas 16) etc.
Donc la, pour l'alignement mémoire de test structures et leur composition il faut faire attention a ca.
Sur les x86 on dispose des instructions assembleur permettant les opération sur les bits sans dégradation notable de performance.
Donc le problème n'est pas ce que ton proc peut faire ou pas mais ce que ton compilateur va générer comme code pour le faire, je te conseille donc de lire en assembleur un prog simple sur la manipulation des champs de bit par ton compilo pour juger du résultat (pertinent ou pas).
En général, le nombre d'instruction est plutôt parlant pour voir si c'est rapide ou pas mais ce n'est pas une règle absolu car les instructions de lecture en mémoire et d’opération arithmétique ne sont pas équivalentes en temps d’exécution.
# Jouons avec les bits
Posté par Def . Évalué à 4.
Sans trop d'hésitations, s'il y a beaucoup de données il vaut mieux limiter la pression sur les caches et les accès mémoires. La décapsulation par le CPU a un coût négligeable (essentiellement des opérations logiques et des décalages, il aime faire ça) devant les I/O sur le bus mémoire.
Donc pour privilégier les performances dans ce cas précis, les champs sont tout indiqué. La seule mise en garde étant de ne pas faire d'optimisation prématurée, d'autant que la manipulation des champs de bits est plus sujette à erreur qu'un accès direct.
Naturellement, prendre soins d'abstraire cette partie du code en tant compte des contraintes respectives de ces deux options te permettra de choisir l'option la plus appropriée le moment venu.
[^] # Re: Jouons avec les bits
Posté par lolop (site web personnel) . Évalué à 3.
Merci à tous les trois.
Je vais essayer en utilisant simplement les champs de bits dans les structures C, ça reste lisible et sans plus de risque d'erreur (c'est le compilo qui s'occupe des problèmes de masquage), je n'aurais qu'à repasser les données en 32 / 64 bits complets pour tester l'effet cache vs alignement.
Votez les 30 juin et 7 juillet, en connaissance de cause. http://www.pointal.net/VotesDeputesRN
[^] # Re: Jouons avec les bits
Posté par Obsidian . Évalué à 2.
Hello,
Pense à "#pragma pack" si ton objectif est de minimiser l'espace mémoire. Par ailleurs, veille à bien choisir les classes de stockage adaptées en fonction de l'exploitation que tu fais de tes données. Pour reprendre tes exemples (et pour faire simple) : beaucoup de lecture aléatoire mais peu d'insertions : tableau trié ; Lecture séquentielle, mais insertion ou suppression fréquente : liste chaînée, etc.
[^] # Re: Jouons avec les bits
Posté par lolop (site web personnel) . Évalué à 2.
Pour le pragma pack, c'est déjà fait.
Pour les structures, il y a pas mal de listes, mais je les implémente via des index dans des tableaux + une "liste" des places libres - ça me facilitera aussi le stockage sur disque / relecture directement sous forme binaire. Et l'utilisation de tableau assure que les éléments seront contigus en mémoire…
Votez les 30 juin et 7 juillet, en connaissance de cause. http://www.pointal.net/VotesDeputesRN
# the root of all evil
Posté par Krunch (site web personnel) . Évalué à 2.
Écrit ton programme sans te soucier trop des performances (bon, il faut penser un minimum à une architecture qui tient la route mais la taille des structures de données devrait vraiment être secondaire à ce stade puisque tu peux les changer relativement facilement sans tout réécrire). Une fois qu'il fonctionne, tu peux commencer à profiler au niveau performance et mémoire puis seulement tu peux envisager d'optimiser telle ou telle partie.
http://en.wikipedia.org/wiki/Program_optimization#When_to_optimize
Also,
pertinent adj. Approprié : qui se rapporte exactement à ce dont il est question.
[^] # Re: the root of all evil
Posté par lolop (site web personnel) . Évalué à 2.
Je connais.
C'est une réécriture d'un code existant, avec pour but de séparer la partie calcul dans une bibliothèque utilisable indépendamment de la partie interface utilisateur. Le côté algo fonctionne donc déjà, ça serait bien qu'il tourne correctement et efficacement, et si ça peut se faire avec quelques fonctionnalités standard du langage qui ne changent quasiment pas le code (champs de bits), autant en profiter.
Votez les 30 juin et 7 juillet, en connaissance de cause. http://www.pointal.net/VotesDeputesRN
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.