Articulo de referencia

Cola de entrada de precarga

La obtención anticipada de los códigos de operación de la memoria del programa se conoce como precarga y se realiza mediante una cola de entrada de precarga (PIQ). Las instrucci...

La obtención anticipada de los códigos de operación de la memoria del programa se conoce como precarga y se realiza mediante una cola de entrada de precarga (PIQ). Las instrucciones precargadas se almacenan en una cola . La obtención anticipada de los códigos de operación, antes de su ejecución, aumenta la eficiencia general del procesador , incrementando su velocidad. El procesador ya no tiene que esperar a que finalicen las operaciones de acceso a memoria para la siguiente instrucción. Esta arquitectura se utilizó ampliamente en el microprocesador Intel 8086 .

Introducción

La segmentación de instrucciones se convirtió en un elemento clave del diseño de arquitecturas informáticas durante la década de 1960 debido a la necesidad de una computación más rápida y eficiente. La segmentación de instrucciones es un concepto más amplio, y la mayoría de los procesadores modernos cargan sus instrucciones varios ciclos de reloj antes de ejecutarlas. Esto se logra precargando el código máquina desde la memoria a una cola de precarga .

Este comportamiento solo se aplica a las computadoras von Neumann (es decir, no a las computadoras con arquitectura Harvard ) que pueden ejecutar código automodificable y cuentan con algún tipo de segmentación de instrucciones . Casi todas las computadoras modernas de alto rendimiento cumplen con estos tres requisitos. [ 1 ]

Por lo general, el comportamiento de precarga de la cola PIQ es invisible para el modelo de programación de la CPU. Sin embargo, existen algunas circunstancias en las que el comportamiento de la cola PIQ es visible y el programador debe tenerlo en cuenta.

Cuando un procesador x86 cambia de modo real a modo protegido y viceversa, es necesario vaciar la cola PIQ; de lo contrario, la CPU seguirá traduciendo el código máquina como si se hubiera escrito en su último modo. Si no se vacía la cola PIQ, el procesador podría traducir el código incorrectamente y generar una excepción de instrucción no válida .

Al ejecutar código automodificable , un cambio en el código del procesador inmediatamente anterior a la ubicación de ejecución actual podría no alterar la forma en que el procesador interpreta el código, ya que este ya está cargado en su PIQ. Simplemente ejecuta la copia anterior ya cargada en el PIQ en lugar de la versión nueva y modificada del código en su RAM o caché .

Este comportamiento de la cola PIQ permite determinar si el código se ejecuta en un emulador o directamente en el hardware de una CPU real. La mayoría de los emuladores probablemente nunca simularán este comportamiento. Si el tamaño de la cola PIQ es cero (los cambios en el código siempre afectan al estado del procesador de inmediato), se puede deducir que el código se ejecuta en un emulador o que el procesador invalida la cola PIQ al escribir en las direcciones cargadas en ella.

Evaluación del desempeño basada en la teoría de colas

Fue A. K. Erlang (1878-1929) quien concibió por primera vez el concepto de cola como solución a la congestión en el tráfico telefónico. Se proponen diferentes modelos de colas para simular de forma aproximada los sistemas de colas en tiempo real, de modo que puedan analizarse matemáticamente para distintas especificaciones de rendimiento.

Los modelos de colas se pueden representar utilizando la notación de Kendall :

A1/A2/A3/A4

dónde:

  • A1 es la distribución del tiempo entre dos llegadas.
  • A2 es la distribución del tiempo de servicio
  • A3 es el número total de servidores
  • A4 es la capacidad del sistema
  1. Modelo M/M/1 (Cola Única, Servidor Único/ Markoviano ): En este modelo, los elementos de la cola se atienden según el principio de primero en llegar, primero en ser atendido. Dados los índices medios de llegada y servicio, los índices reales varían aleatoriamente alrededor de estos valores promedio y, por lo tanto, deben determinarse mediante una función de distribución de probabilidad acumulativa . [ 2 ]
  2. Modelo M/M/r : Este modelo es una generalización del modelo básico M/M/1, donde múltiples servidores operan en paralelo. Este tipo de modelo también puede simular escenarios con usuarios impacientes que abandonan la cola inmediatamente si no reciben servicio. Esto también se puede modelar mediante un proceso de Bernoulli con solo dos estados: éxito y fracaso. El mejor ejemplo de este modelo son nuestros sistemas telefónicos fijos habituales. [ 3 ]
  3. Modelo M/G/1 (modelo de entrada finita de Takacs)  : Este modelo se utiliza para analizar casos avanzados. Aquí, la distribución del tiempo de servicio ya no es un proceso de Markov . Este modelo considera el caso de más de una máquina averiada reparada por un solo técnico. El tiempo de servicio para cualquier usuario aumentará en este caso. [ 4 ]

Generalmente, en aplicaciones como las colas de entrada con precarga, se utiliza el modelo M/M/1 debido al uso limitado de las funcionalidades de la cola. En este modelo, en consonancia con los microprocesadores, el usuario actúa como unidad de ejecución y el servidor como unidad de interfaz del bus.

Cola de instrucciones

El procesador ejecuta un programa obteniendo las instrucciones de la memoria y ejecutándolas. Generalmente, la velocidad de ejecución del procesador es mucho mayor que la velocidad de acceso a la memoria. La cola de instrucciones se utiliza para precargar las siguientes instrucciones en un búfer independiente mientras el procesador ejecuta la instrucción actual.

Con una arquitectura de cuatro etapas , la velocidad a la que se ejecutan las instrucciones puede ser hasta cuatro veces mayor que la de la ejecución secuencial. [ 5 ]

El procesador suele tener dos unidades separadas para obtener las instrucciones y para ejecutarlas. [ 6 ] [ 7 ]

La implementación de una arquitectura de segmentación solo es posible si la unidad de interfaz de bus y la unidad de ejecución son independientes. Mientras la unidad de ejecución decodifica o ejecuta una instrucción que no requiere el uso de los buses de datos y direcciones , la unidad de interfaz de bus obtiene los códigos de operación de las instrucciones de la memoria.

Este proceso es mucho más rápido que enviar una dirección, leer el código de operación y luego decodificarlo y ejecutarlo. Obtener la siguiente instrucción mientras se decodifica o ejecuta la instrucción actual se denomina segmentación (pipelining). [ 8 ]

El procesador 8086 tiene una tubería de instrucciones con precarga de seis bytes, mientras que el 8088 tiene una con precarga de cuatro bytes. Mientras la Unidad de Ejecución ejecuta la instrucción actual, la unidad de interfaz de bus lee hasta seis (o cuatro) bytes de códigos de operación por adelantado desde la memoria. Las longitudes de la cola se eligieron en función de estudios de simulación. [ 9 ]

Se produce una excepción cuando la unidad de ejecución encuentra una instrucción de salto , ya sea una instrucción de salto o una instrucción de llamada. En este caso, se debe vaciar toda la cola y recuperar de la memoria el contenido al que apunta el puntero de instrucción.

Desventajas

Los procesadores que implementan el algoritmo de precarga de la cola de instrucciones son técnicamente muy avanzados. La complejidad del diseño de la CPU de estos procesadores es mucho mayor que la de los procesadores convencionales. Esto se debe principalmente a la necesidad de implementar dos unidades separadas, la BIU y la EU , que operan de forma independiente.

A medida que aumenta la complejidad de estos chips, también aumenta su coste. Estos procesadores son relativamente más caros que sus homólogos que no cuentan con la cola de precarga de entrada.

Sin embargo, estas desventajas se ven ampliamente compensadas por la mejora en el tiempo de ejecución del procesador. Tras la introducción de la cola de instrucciones de precarga en el procesador 8086, todos los procesadores posteriores han incorporado esta característica.

Código de ejemplo x86

code_starts_here: mov bx , ahead mov word ptr cs :[ bx ], 9090h ahead: jmp near to_the_end ; Algún otro código to_the_end:

Este programa automodificable sobrescribirá el salto `to_the_end` con dos instrucciones NOP (codificadas como 0x9090 ). El salto `to_the_end` se ensambla en dos bytes de código máquina, por lo que las dos instrucciones NOP solo sobrescribirán este salto y nada más. (Es decir, el salto se reemplaza con un código que no hace nada).

Dado que el código máquina del salto ya está leído en el PIQ, y probablemente también ya ha sido ejecutado por el procesador ( los procesadores superescalares ejecutan varias instrucciones a la vez, pero "simulan" que no lo hacen debido a la necesidad de compatibilidad con versiones anteriores ), el cambio del código no tendrá ningún efecto en el flujo de ejecución.

Programa de ejemplo para detectar el tamaño

Este es un ejemplo de NASM ( algoritmo de lenguaje ensamblador x86 automodificable con sintaxis) que determina el tamaño del PIQ:

El código comienza aquí: xor bx , bx ; poner a cero el registro bx xor ax , ax ; poner a cero el registro axmov dx , cs mov [ code_segment ], dx ; "calcula" el segmento de código en el salto lejano más abajo (edx también aquí)alrededor: cmp ax , 1 ; comprobar si ax ha sido modificado je found_size ; 0x90 = opcode "nop" (NO oPeration) mov byte [ nop_field + bx ], 0x90 inc bxdb 0xEA ; 0xEA = opcode "salto lejano" dw flush_queue ; debe ir seguido de offset (rm = "dw", pm = "dd") code_segment: dw 0 ; y luego el segmento de código (calculado arriba) flush_queue: ; 0x40 = opcode "inc ax" (INCrease ax) mov byte [ nop_field + bx ], 0x40 nop_field: veces 256 nop jmp around found_size: ; ; el registro bx ahora contiene el tamaño de PIQ ; este código es para [[modo real]] y [[modo protegido de 16 bits]], pero podría cambiarse fácilmente para ; que funcione también para [[modo protegido de 32 bits]]. Simplemente cambie "dw" por ; el offset a "dd". También necesita cambiar dx a edx en la parte superior como ; también. (dw y dx = direccionamiento de 16 bits, dd y edx = direccionamiento de 32 bits) ;

Básicamente, este código modifica el flujo de ejecución y determina, mediante fuerza bruta, el tamaño del PIQ. "¿A qué distancia debo modificar el código que tengo delante para que tenga efecto?" Si está demasiado cerca (ya se encuentra dentro del PIQ), la actualización no tendrá ningún efecto. Si está lo suficientemente lejos, la modificación del código afectará al programa, que entonces habrá determinado el tamaño del PIQ del procesador. Si este código se ejecuta en un sistema operativo multitarea, el cambio de contexto puede generar un valor erróneo.

Véase también

Referencias

  1. "Centro de información de ARM" . Artículos de conocimiento de soporte técnico de ARM .
  2. Hayes, John (1998). Arquitectura y organización de computadoras (Segunda edición). McGraw-Hill. 
  3. Feller, William (1968). Introducción a la teoría de la probabilidad y sus aplicaciones (Segunda edición). John Wiley and Sons. 
  4. Papoulis, Athanasios; S.Unnikrishna Pillai (2008). Probabilidad, variables aleatorias y procesos estocásticos (Cuarta ed.). McGraw-Hill. págs. 784 a 800.  
  5. ^ Zaky, Safwat; V. Carl Hamacher; Zvonko G. Vranesic (1996). Organización informática (Cuarta ed.). McGraw-Hill. págs. 310–329 . ISBN   0-07-114309-2.
  6. "Diagrama de bloques de la CPU 8086" .
  7. Hall, Douglas (2006). Microprocesadores e interconexión . Tata McGraw-Hill. pág. 2.12. ISBN  0-07-060167-4.
  8. Hall, Douglas (2006). Microprocesadores e interconexión . Nueva Delhi: Tata McGraw-Hill. págs. 2.13 – 2.14 . ISBN  0-07-060167-4.
  9. McKevitt, James; Bayliss, John (marzo de 1979). "Nuevas opciones de chips grandes". IEEE Spectrum . 16 (3): 28– 34. doi : 10.1109/MSPEC.1979.6367944 . S2CID 25154920 .