Simulateurs de systèmes informatiques : le simulateur complet familier et la barre et la trace inconnues

Dans la deuxième partie de l'article sur les simulateurs de systèmes informatiques, je continuerai à parler sous une forme introductive simple des simulateurs informatiques, à savoir de la simulation pleine plateforme, que l'utilisateur moyen rencontre le plus souvent, ainsi que de l'horloge. -modèle d'horloge et traces, qui sont plus courants dans les cercles des développeurs.

Simulateurs de systèmes informatiques : le simulateur complet familier et la barre et la trace inconnues

В la première partie J'ai parlé de ce que sont les simulateurs en général, ainsi que des niveaux de simulation. Maintenant, sur la base de ces connaissances, je propose d'approfondir un peu et de parler de la simulation complète, de la manière de collecter des traces, de ce qu'il faut en faire plus tard, ainsi que de l'émulation microarchitecturale horloge par horloge.

Simulateur plateforme complète, ou « Seul sur le terrain n'est pas un guerrier »

Si vous souhaitez étudier le fonctionnement d'un périphérique spécifique, par exemple une carte réseau, ou écrire un micrologiciel ou un pilote pour ce périphérique, un tel périphérique peut être simulé séparément. Cependant, son utilisation isolée du reste de l’infrastructure n’est pas très pratique. Pour exécuter le pilote correspondant, vous aurez besoin d'un processeur central, de mémoire, d'un accès à un bus de données, etc. De plus, le pilote nécessite un système d'exploitation (OS) et une pile réseau pour fonctionner. De plus, un générateur de paquets et un serveur de réponses distincts peuvent être requis.

Un simulateur complet crée un environnement pour exécuter une pile logicielle complète, qui comprend tout, du BIOS et du chargeur de démarrage au système d'exploitation lui-même et à ses différents sous-systèmes, tels que la même pile réseau, les pilotes et les applications au niveau utilisateur. Pour ce faire, il implémente les modèles logiciels de la plupart des appareils informatiques : processeur et mémoire, disque, périphériques d'entrée/sortie (clavier, souris, écran), ainsi que la même carte réseau.

Vous trouverez ci-dessous un schéma fonctionnel du chipset x58 d'Intel. Un simulateur informatique complet sur ce chipset nécessite la mise en œuvre de la plupart des périphériques répertoriés, y compris ceux à l'intérieur de l'IOH (Input/Output Hub) et ICH (Input/Output Controller Hub), qui ne sont pas représentés en détail sur le schéma fonctionnel. . Cependant, comme le montre la pratique, il n'y a pas beaucoup d'appareils qui ne sont pas utilisés par le logiciel que nous allons exécuter. Il n'est pas nécessaire de créer des modèles de tels appareils.

Simulateurs de systèmes informatiques : le simulateur complet familier et la barre et la trace inconnues

Le plus souvent, les simulateurs complets sont implémentés au niveau des instructions du processeur (ISA, voir ci-dessous). article précédent). Cela vous permet de créer le simulateur lui-même relativement rapidement et à moindre coût. Le niveau ISA est également bon car il reste plus ou moins constant, contrairement par exemple au niveau API/ABI qui change plus souvent. De plus, l'implémentation au niveau des instructions vous permet d'exécuter un logiciel binaire dit non modifié, c'est-à-dire d'exécuter du code déjà compilé sans aucune modification, exactement comme il est utilisé sur du matériel réel. En d’autres termes, vous pouvez faire une copie (« dump ») de votre disque dur, le spécifier comme image pour un modèle dans un simulateur pleine plateforme, et le tour est joué ! – Le système d'exploitation et les autres programmes sont chargés dans le simulateur sans aucune action supplémentaire.

Performances du simulateur

Simulateurs de systèmes informatiques : le simulateur complet familier et la barre et la trace inconnues

Comme mentionné ci-dessus, le processus de simulation de l'ensemble du système, c'est-à-dire de tous ses appareils, est une entreprise plutôt lente. Si vous implémentez également tout cela à un niveau très détaillé, par exemple microarchitectural ou logique, l'exécution deviendra extrêmement lente. Mais le niveau d'instruction est un choix approprié et permet au système d'exploitation et aux programmes de s'exécuter à des vitesses suffisantes pour que l'utilisateur puisse interagir confortablement avec eux.

Il conviendrait ici d'aborder le sujet des performances du simulateur. Elle se mesure généralement en IPS (instructions par seconde), plus précisément en MIPS (millions IPS), c'est-à-dire le nombre d'instructions processeur exécutées par le simulateur en une seconde. Dans le même temps, la vitesse de la simulation dépend également des performances du système sur lequel la simulation elle-même s'exécute. Par conséquent, il peut être plus correct de parler du « ralentissement » du simulateur par rapport au système d’origine.

Les simulateurs pleine plateforme les plus courants du marché, tels que QEMU, VirtualBox ou VmWare Workstation, ont de bonnes performances. L'utilisateur peut même ne pas remarquer que des travaux sont en cours dans le simulateur. Cela se produit grâce aux capacités de virtualisation spéciales implémentées dans les processeurs, aux algorithmes de traduction binaire et à d'autres choses intéressantes. Tout cela fait l'objet d'un article séparé, mais en bref, la virtualisation est une fonctionnalité matérielle des processeurs modernes qui permet aux simulateurs de ne pas simuler des instructions, mais de les envoyer pour exécution directement à un processeur réel, si, bien sûr, les architectures de le simulateur et le processeur sont similaires. La traduction binaire est la traduction du code machine invité en code hôte et son exécution ultérieure sur un processeur réel. En conséquence, la simulation n’est que légèrement plus lente, 5 à 10 fois, et s’exécute même souvent à la même vitesse que le système réel. Bien que cela soit influencé par de nombreux facteurs. Par exemple, si nous voulons simuler un système avec plusieurs dizaines de processeurs, la vitesse diminuera immédiatement de plusieurs dizaines de fois. D'un autre côté, les simulateurs comme Simics dans les dernières versions prennent en charge le matériel hôte multiprocesseur et parallélisent efficacement les cœurs simulés sur les cœurs d'un processeur réel.

Si nous parlons de la vitesse de simulation microarchitecturale, elle est généralement de plusieurs ordres de grandeur, environ 1000 10000 à XNUMX XNUMX fois plus lente que l'exécution sur un ordinateur classique, sans simulation. Et les implémentations au niveau des éléments logiques sont plus lentes de plusieurs ordres de grandeur. Par conséquent, un FPGA est utilisé comme émulateur à ce niveau, ce qui peut augmenter considérablement les performances.

Le graphique ci-dessous montre une dépendance approximative de la vitesse de simulation aux détails du modèle.

Simulateurs de systèmes informatiques : le simulateur complet familier et la barre et la trace inconnues

Simulation battement par battement

Malgré leur faible vitesse d’exécution, les simulateurs microarchitecturaux sont assez courants. La simulation des blocs internes du processeur est nécessaire afin de simuler avec précision le temps d'exécution de chaque instruction. Un malentendu peut survenir ici - après tout, semble-t-il, pourquoi ne pas simplement programmer le temps d'exécution de chaque instruction. Mais un tel simulateur sera très imprécis, puisque le temps d'exécution d'une même instruction peut différer d'un appel à l'autre.

L'exemple le plus simple est une instruction d'accès à la mémoire. Si l'emplacement mémoire demandé est disponible dans le cache, alors le temps d'exécution sera minime. Si ces informations ne sont pas dans le cache (« cache miss »), cela augmentera considérablement le temps d'exécution de l'instruction. Ainsi, un modèle de cache est requis pour une simulation précise. Cependant, le problème ne se limite pas au modèle de cache. Le processeur n'attendra pas simplement que les données soient récupérées de la mémoire lorsqu'elles ne sont pas dans le cache. Au lieu de cela, il commencera à exécuter les instructions suivantes, en choisissant celles qui ne dépendent pas du résultat de la lecture en mémoire. Il s’agit de l’exécution dite « hors service » (OOO, out of order exécution), nécessaire pour minimiser le temps d’inactivité du processeur. La modélisation des blocs processeur correspondants permettra de prendre en compte tout cela lors du calcul du temps d'exécution des instructions. Parmi ces instructions, exécutées alors que le résultat de la lecture en mémoire est attendu, une opération de saut conditionnel peut intervenir. Si le résultat de la condition est inconnu pour le moment, là encore, le processeur n'arrête pas l'exécution, mais fait une « supposition », effectue le branchement approprié et continue d'exécuter de manière proactive les instructions à partir du point de transition. Un tel bloc, appelé prédicteur de branchement, doit également être implémenté dans le simulateur microarchitectural.

L'image ci-dessous montre les principaux blocs du processeur, il n'est pas nécessaire de les connaître, elle est présentée uniquement pour montrer la complexité de la mise en œuvre microarchitecturale.

Simulateurs de systèmes informatiques : le simulateur complet familier et la barre et la trace inconnues

Le fonctionnement de tous ces blocs dans un processeur réel est synchronisé par des signaux d'horloge spéciaux, et la même chose se produit dans le modèle. Un tel simulateur microarchitectural est appelé cycle précis. Son objectif principal est de prédire avec précision les performances du processeur en cours de développement et/ou de calculer le temps d'exécution d'un programme spécifique, par exemple un benchmark. Si les valeurs sont inférieures à celles requises, il faudra alors modifier les algorithmes et les blocs processeur ou optimiser le programme.

Comme indiqué ci-dessus, la simulation horloge par horloge est très lente, elle n'est donc utilisée que lors de l'étude de certains moments du fonctionnement d'un programme, où il est nécessaire de connaître la vitesse réelle d'exécution du programme et d'évaluer les performances futures de l'appareil dont le prototype est en cours de simulation.

Dans ce cas, un simulateur fonctionnel est utilisé pour simuler le temps d’exécution restant du programme. Comment cette combinaison d’usages se produit-elle dans la réalité ? Tout d'abord, le simulateur fonctionnel est lancé, sur lequel sont chargés le système d'exploitation et tout le nécessaire pour exécuter le programme à l'étude. Après tout, nous ne nous intéressons pas au système d'exploitation lui-même, ni aux premières étapes de lancement du programme, de sa configuration, etc. Cependant, nous ne pouvons pas non plus ignorer ces parties et passer immédiatement à l'exécution du programme à partir du milieu. Toutes ces étapes préliminaires sont donc exécutées sur un simulateur fonctionnel. Une fois le programme exécuté jusqu'au moment qui nous intéresse, deux options sont possibles. Vous pouvez remplacer le modèle par un modèle horloge par cycle et poursuivre l'exécution. Le mode de simulation qui utilise du code exécutable (c'est-à-dire des fichiers de programme compilés réguliers) est appelé simulation pilotée par l'exécution. Il s’agit de l’option de simulation la plus courante. Une autre approche est également possible : la simulation basée sur les traces.

Simulation basée sur les traces

Il se compose de deux étapes. À l'aide d'un simulateur fonctionnel ou sur un système réel, un journal des actions du programme est collecté et écrit dans un fichier. Ce journal est appelé une trace. En fonction de ce qui est examiné, la trace peut inclure des instructions exécutables, des adresses mémoire, des numéros de port et des informations d'interruption.

L'étape suivante consiste à « jouer » la trace, lorsque le simulateur horloge par horloge lit la trace et exécute toutes les instructions qui y sont écrites. A la fin, nous obtenons le temps d'exécution de cette partie du programme, ainsi que diverses caractéristiques de ce processus, par exemple le pourcentage de hits dans le cache.

Une caractéristique importante du travail avec des traces est le déterminisme, c'est-à-dire qu'en exécutant la simulation de la manière décrite ci-dessus, nous reproduisons encore et encore la même séquence d'actions. Cela permet, en modifiant les paramètres du modèle (taille du cache, du tampon et de la file d'attente) et en utilisant différents algorithmes internes ou en les ajustant, d'étudier comment un paramètre particulier affecte les performances du système et quelle option donne les meilleurs résultats. Tout cela peut être fait avec un modèle de périphérique prototype avant de créer un prototype matériel réel.

La complexité de cette approche réside dans la nécessité d'exécuter d'abord l'application et de collecter la trace, ainsi que dans la taille énorme du fichier de trace. Les avantages incluent le fait qu'il suffit de simuler uniquement la partie du dispositif ou de la plate-forme qui nous intéresse, alors que la simulation par exécution nécessite généralement un modèle complet.

Ainsi, dans cet article, nous avons examiné les fonctionnalités de la simulation complète, parlé de la vitesse de mise en œuvre à différents niveaux, de la simulation horloge par cycle et des traces. Dans le prochain article, je décrirai les principaux scénarios d'utilisation des simulateurs, tant à des fins personnelles que du point de vue du développement dans les grandes entreprises.

Source: habr.com

Ajouter un commentaire