2013-04-06 2 views
2

Je construis une petite machine virtuelle bytecode qui fonctionnera sur une variété de plates-formes, y compris les environnements exotiques embarqués et microcontrôleurs.Comment charger le plus grand entier possible dans une opération de mémoire?

Chaque code d'opération dans ma machine virtuelle peut être de longueur variable (pas plus de 4 octets, pas moins de 1 octet). En interprétant les opcodes, je veux créer un minuscule "cache" pour l'opcode actuel. Cependant, en raison de son utilisation sur de nombreuses plates-formes différentes, c'est difficile à faire.

Alors, voici quelques exemples de comportement attendu:

  1. Sur un microcontrôleur 8 bits avec un bus mémoire 8 bits, je le veux à la charge seulement 1 octet parce qu'il prendrait Plusieurs opérations (lentes) de mémoire à charger plus, et en théorie, il peut ne nécessiter que 1 octet pour exécuter l'opcode
  2. Sur un 8086 (16 bits), je voudrais charger 2 octets parce que pour charger seulement 1 octet nous jetterions essentiellement des données utiles à lire plus tard, mais je ne veux pas charger plus de 2 octets car cela prendrait plusieurs opérations
  3. Sur un traitement ARM 32 bits Je voudrais charger 4 octets parce que sinon nous lançons des données qui pourraient être lues à nouveau, ou nous faisons plusieurs opérations

Je dirais que cela pourrait être manipulé facilement en supposant simplement que unsigned int est assez bon, mais sur les microcontrôleurs AVR 8 bits, int est défini comme 16 bits, mais la largeur du bus de données mémoire est seulement 8 bits, donc 2 opérations de chargement de mémoire seraient nécessaires.

Quoi qu'il en soit, les idées actuelles:

utilisant uint_fast16_t semble fonctionner comme prévu sur la plupart des plates-formes (32 bits sur ARM 16 bits, sur 8086, 64 bits sur x86-64). Cependant, il laisse clairement de côté AVR et d'autres microcontrôleurs 8 bits.

Je pensais à l'aide pourrait fonctionner, mais il semble sur la plupart des plates-formes qu'il est défini comme étant unsigned char, ce qui est certainement pas optimale

En outre, il y a un autre problème qui doit être résolu ainsi: mémoire non alignés accès. Sur x86, cela ne va probablement pas poser de problème (en théorie, il fait 2 opérations de mémoire, mais il est probablement caché dans le matériel), mais sur ARM je sais que faire un accès 32 bits non aligné peut coûter 3 fois autant qu'une seule charge de 32 bits alignée. Si l'adresse est non alignée, je veux charger l'option alignée et obtenir autant de données que possible, mais à tout prix éviter une autre opération de mémoire

Y at-il un moyen de le faire en quelque sorte en utilisant un préprocesseur magique comprend ou une telle, ou Est-ce qu'il suffit de définir manuellement la taille de cache optimale avant de compiler pour la plate-forme?

+0

Votre procédure de construction (par exemple votre 'Makefile') pourrait exécuter une commande de configuration, par ex. générer un fichier d'en-tête contenant le '# define' approprié ... Mais je ne suis pas sûr que votre idée de" mise en cache "rende votre VM plus rapide ... –

+0

@BasileStarynkevitch Pourquoi 4 charges de mémoire discrètes seraient-elles jamais plus rapides qu'une seule charge discrète? Surtout quand vous jetez des données au niveau de l'assemblage. Aussi, je voudrais vraiment éviter d'avoir à utiliser du code pour générer des trucs de configuration (j'aime mon processus de construction simple :)) – Earlz

+0

Parce que le compilateur peut les optimiser, et parce que la plupart des coûts d'interprétation VM sont ailleurs ... Si vous ne voulez pas générer des choses configurables, vous ne pouvez pas résoudre votre problème ... En outre, votre charge de 4 octets sera généralement non alignée, ce qui a un coût de performance significatif. Vous essayez de micro-optimiser manuellement, ce qui est presque toujours une mauvaise chose à faire (surtout si vous ne l'avez pas référencé). Laissez les micro-optimisations au compilateur. –

Répondre

0

Il n'y a pas de manière automatique de le faire en utilisant les types ou les informations fournis par la norme C (dans les en-têtes, etc.).

Des problèmes de ce type sont parfois traités en exécutant et en mesurant un échantillon de code sur la plate-forme cible et en utilisant les résultats pour déterminer le code à utiliser en pratique. Les échantillons peuvent être exécutés pendant une construction puis intégrés dans le code final ou peuvent être exécutés au début de chaque exécution du programme, puis utilisés pendant la durée de l'exécution.

Questions connexes