Simuladores de sistemas informáticos: el conocido simulador de plataforma completa y el desconocido bar and trace

En la segunda parte del artículo sobre simuladores de sistemas informáticos, continuaré hablando de una forma introductoria sencilla sobre los simuladores de ordenador, es decir, sobre la simulación de plataforma completa que el usuario medio encuentra con mayor frecuencia, así como sobre el reloj. -modelo de reloj y trazas, que son más comunes en los círculos de desarrolladores.

Simuladores de sistemas informáticos: el conocido simulador de plataforma completa y el desconocido bar and trace

В la primera parte Hablé de qué son los simuladores en general, así como de los niveles de simulación. Ahora, basándome en ese conocimiento, propongo profundizar un poco más y hablar sobre la simulación de plataforma completa, cómo recopilar trazas, qué hacer con ellas más tarde, así como sobre la emulación de microarquitectura reloj por reloj.

Simulador de plataforma completo, o "Solo en el campo no está un guerrero"

Si desea estudiar el funcionamiento de un dispositivo específico, por ejemplo, una tarjeta de red, o escribir firmware o un controlador para este dispositivo, dicho dispositivo se puede simular por separado. Sin embargo, utilizarlo de forma aislada del resto de la infraestructura no es muy conveniente. Para ejecutar el controlador correspondiente, necesitará un procesador central, memoria, acceso a un bus de datos, etc. Además, el controlador requiere un sistema operativo (SO) y una pila de red para funcionar. Además, es posible que se requiera un generador de paquetes y un servidor de respuesta separados.

Un simulador de plataforma completa crea un entorno para ejecutar una pila de software completa, que incluye todo, desde el BIOS y el gestor de arranque hasta el propio sistema operativo y sus diversos subsistemas, como la misma pila de red, controladores y aplicaciones a nivel de usuario. Para ello, implementa modelos de software de la mayoría de los dispositivos informáticos: procesador y memoria, disco, dispositivos de entrada/salida (teclado, ratón, pantalla), así como la misma tarjeta de red.

A continuación se muestra un diagrama de bloques del chipset x58 de Intel. Un simulador de computadora de plataforma completa en este conjunto de chips requiere la implementación de la mayoría de los dispositivos enumerados, incluidos aquellos dentro del IOH (concentrador de entrada/salida) y el ICH (concentrador de controlador de entrada/salida), que no se describen en detalle en el diagrama de bloques. . Aunque, como demuestra la práctica, no son muchos los dispositivos que no sean utilizados por el software que vamos a ejecutar. No es necesario crear modelos de dichos dispositivos.

Simuladores de sistemas informáticos: el conocido simulador de plataforma completa y el desconocido bar and trace

La mayoría de las veces, los simuladores de plataforma completa se implementan en el nivel de instrucción del procesador (ISA, ver más abajo). Artículo anterior). Esto le permite crear el propio simulador de forma relativamente rápida y económica. El nivel ISA también es bueno porque permanece más o menos constante, a diferencia de, por ejemplo, el nivel API/ABI, que cambia con más frecuencia. Además, la implementación a nivel de instrucción permite ejecutar el llamado software binario no modificado, es decir, ejecutar código ya compilado sin ningún cambio, exactamente como se usa en el hardware real. En otras palabras, puede hacer una copia (“volcado”) de su disco duro, especificarlo como imagen para un modelo en un simulador de plataforma completa y ¡listo! – El sistema operativo y otros programas se cargan en el simulador sin ninguna acción adicional.

Rendimiento del simulador

Simuladores de sistemas informáticos: el conocido simulador de plataforma completa y el desconocido bar and trace

Como se mencionó anteriormente, el proceso de simulación de todo el sistema, es decir, todos sus dispositivos, es una tarea bastante lenta. Si también implementa todo esto en un nivel muy detallado, por ejemplo, microarquitectónico o lógico, la ejecución será extremadamente lenta. Pero el nivel de instrucción es una opción adecuada y permite que el sistema operativo y los programas se ejecuten a velocidades suficientes para que el usuario interactúe con ellos cómodamente.

Aquí sería apropiado abordar el tema del rendimiento del simulador. Suele medirse en IPS (instrucciones por segundo), más precisamente en MIPS (millones de IPS), es decir, el número de instrucciones del procesador ejecutadas por el simulador en un segundo. Al mismo tiempo, la velocidad de la simulación también depende del rendimiento del sistema en el que se ejecuta la simulación. Por tanto, puede ser más correcto hablar de "desaceleración" del simulador en comparación con el sistema original.

Los simuladores de plataforma completa más habituales del mercado, como QEMU, VirtualBox o VmWare Workstation, tienen un buen rendimiento. Es posible que el usuario ni siquiera se dé cuenta de que se está trabajando en el simulador. Esto sucede gracias a las capacidades especiales de virtualización implementadas en los procesadores, algoritmos de traducción binaria y otras cosas interesantes. Todo este es un tema para un artículo separado, pero en resumen, la virtualización es una característica de hardware de los procesadores modernos que permite a los simuladores no simular instrucciones, sino enviarlas para su ejecución directamente a un procesador real, si, por supuesto, las arquitecturas de el simulador y el procesador son similares. La traducción binaria es la traducción del código de la máquina invitada al código del host y su posterior ejecución en un procesador real. Como resultado, la simulación es sólo un poco más lenta, de 5 a 10 veces, y a menudo incluso funciona a la misma velocidad que el sistema real. Aunque esto está influenciado por muchos factores. Por ejemplo, si queremos simular un sistema con varias docenas de procesadores, la velocidad disminuirá inmediatamente varias docenas de veces. Por otro lado, los simuladores como Simics en las últimas versiones admiten hardware host multiprocesador y paralelizan efectivamente los núcleos simulados en los núcleos de un procesador real.

Si hablamos de la velocidad de la simulación de microarquitectura, entonces suele ser de varios órdenes de magnitud, entre 1000 y 10000 veces más lenta que la ejecución en una computadora normal, sin simulación. Y las implementaciones a nivel de elementos lógicos son más lentas en varios órdenes de magnitud. Por lo tanto, se utiliza una FPGA como emulador a este nivel, lo que puede aumentar significativamente el rendimiento.

El siguiente gráfico muestra una dependencia aproximada de la velocidad de simulación con respecto al detalle del modelo.

Simuladores de sistemas informáticos: el conocido simulador de plataforma completa y el desconocido bar and trace

Simulación latido a latido

A pesar de su baja velocidad de ejecución, los simuladores de microarquitectura son bastante comunes. La simulación de los bloques internos del procesador es necesaria para simular con precisión el tiempo de ejecución de cada instrucción. Aquí pueden surgir malentendidos; después de todo, parecería, ¿por qué no simplemente programar el tiempo de ejecución para cada instrucción? Pero un simulador de este tipo será muy inexacto, ya que el tiempo de ejecución de la misma instrucción puede diferir de una llamada a otra.

El ejemplo más simple es una instrucción de acceso a la memoria. Si la ubicación de memoria solicitada está disponible en la caché, el tiempo de ejecución será mínimo. Si esta información no está en el caché (“error de caché”), esto aumentará considerablemente el tiempo de ejecución de la instrucción. Por tanto, se requiere un modelo de caché para una simulación precisa. Sin embargo, el asunto no se limita al modelo de caché. El procesador no esperará simplemente a que se recuperen los datos de la memoria cuando no estén en la caché. En cambio, comenzará a ejecutar las siguientes instrucciones, eligiendo aquellas que no dependen del resultado de la lectura de la memoria. Esta es la llamada ejecución “fuera de orden” (OOO, ejecución fuera de orden), necesaria para minimizar el tiempo de inactividad del procesador. Modelar los bloques de procesador correspondientes ayudará a tener todo esto en cuenta al calcular el tiempo de ejecución de las instrucciones. Entre estas instrucciones, ejecutadas mientras se espera el resultado de la lectura de la memoria, puede ocurrir una operación de salto condicional. Si el resultado de la condición se desconoce en este momento, entonces nuevamente el procesador no detiene la ejecución, sino que "adivina", realiza la rama apropiada y continúa ejecutando instrucciones de manera proactiva desde el punto de transición. Un bloque de este tipo, llamado predictor de rama, también debe implementarse en el simulador de microarquitectura.

La siguiente imagen muestra los bloques principales del procesador, no es necesario conocerlos, se muestra solo para mostrar la complejidad de la implementación de la microarquitectura.

Simuladores de sistemas informáticos: el conocido simulador de plataforma completa y el desconocido bar and trace

El funcionamiento de todos estos bloques en un procesador real se sincroniza mediante señales de reloj especiales, y lo mismo ocurre en el modelo. Un simulador de microarquitectura de este tipo se denomina ciclo preciso. Su objetivo principal es predecir con precisión el rendimiento del procesador que se está desarrollando y/o calcular el tiempo de ejecución de un programa específico, por ejemplo, un benchmark. Si los valores son inferiores a los requeridos, entonces será necesario modificar los algoritmos y bloques del procesador u optimizar el programa.

Como se muestra arriba, la simulación reloj a reloj es muy lenta, por lo que se utiliza solo cuando se estudian ciertos momentos del funcionamiento de un programa, donde es necesario conocer la velocidad real de ejecución del programa y evaluar el rendimiento futuro del dispositivo cuyo Se está simulando el prototipo.

En este caso, se utiliza un simulador funcional para simular el tiempo de ejecución restante del programa. ¿Cómo se produce en la realidad esta combinación de usos? En primer lugar se lanza el simulador funcional, en el que se carga el SO y todo lo necesario para ejecutar el programa en estudio. Al fin y al cabo, no nos interesa ni el sistema operativo en sí, ni las etapas iniciales de lanzamiento del programa, su configuración, etc. Sin embargo, tampoco podemos saltarnos estas partes y pasar inmediatamente a ejecutar el programa desde la mitad. Por tanto, todos estos pasos preliminares se ejecutan en un simulador funcional. Una vez ejecutado el programa hasta el momento que nos interesa, son posibles dos opciones. Puede reemplazar el modelo con un modelo de reloj por ciclo y continuar con la ejecución. El modo de simulación que utiliza código ejecutable (es decir, archivos de programa compilados normales) se denomina simulación impulsada por la ejecución. Esta es la opción de simulación más común. También es posible otro enfoque: la simulación basada en trazas.

Simulación basada en trazas

Consiste en dos pasos. Utilizando un simulador funcional o en un sistema real, se recopila un registro de las acciones del programa y se escribe en un archivo. Este registro se llama seguimiento. Dependiendo de lo que se esté examinando, el seguimiento puede incluir instrucciones ejecutables, direcciones de memoria, números de puerto e información de interrupción.

El siguiente paso es "reproducir" la traza, cuando el simulador reloj por reloj lee la traza y ejecuta todas las instrucciones escritas en ella. Al final, obtenemos el tiempo de ejecución de esta parte del programa, así como varias características de este proceso, por ejemplo, el porcentaje de aciertos en la caché.

Una característica importante de trabajar con trazas es el determinismo, es decir, al ejecutar la simulación de la manera descrita anteriormente, reproducimos una y otra vez la misma secuencia de acciones. Esto permite, cambiando los parámetros del modelo (caché, búfer y tamaños de cola) y utilizando diferentes algoritmos internos o ajustándolos, estudiar cómo un parámetro particular afecta el rendimiento del sistema y qué opción ofrece los mejores resultados. Todo esto se puede hacer con un modelo de dispositivo prototipo antes de crear un prototipo de hardware real.

La complejidad de este enfoque radica en la necesidad de ejecutar primero la aplicación y recopilar el seguimiento, así como en el enorme tamaño del archivo de seguimiento. Las ventajas incluyen el hecho de que basta con simular sólo la parte del dispositivo o plataforma de interés, mientras que la simulación por ejecución suele requerir un modelo completo.

Entonces, en este artículo analizamos las características de la simulación de plataforma completa, hablamos sobre la velocidad de las implementaciones en diferentes niveles, la simulación de reloj por ciclo y los seguimientos. En el próximo artículo describiré los principales escenarios de uso de simuladores, tanto para fines personales como desde el punto de vista del desarrollo en grandes empresas.

Fuente: habr.com

Añadir un comentario