Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Los motores de videojuegos, como Unreal Engine 4, utilizan varios núcleos cuando producen
escenas complejas. Los motores también pueden usar multithreading para manejar distintas
partes de las "llamadas a draw" (instrucciones que se envían desde la CPU a la GPU acerca
de objetos, texturas y sombreados dentro del videojuego para que se tracen).
Cuando la tecnología Hyper-Threading Intel ® está activa, la CPU expone dos contextos de
ejecución por núcleo físico. Esto significa que un núcleo físico ahora funciona como dos
"núcleos lógicos" que manejan distintos subprocesos de software.
Esquema Principal
Orenga y Manonellas , afirman que para ejecutar las instrucciones, todo procesador dispone
de tres componentes principales:
Registros
Los registros son elementos de memoria de acceso rápido que se encuentran dentro del
procesador. Constituyen un espacio de trabajo para el procesador y se utilizan como un
espacio de almacenamiento temporal. Se implementan utilizando elementos de memoria RAM
estática. Son imprescindibles para ejecutar las instrucciones, entre otros motivos, porque la
ALU solo trabaja con los registros internos del procesador.
Los registros de datos se pueden diferenciar por el formato y el tamaño de los datos
que almacenan.
Unidad aritmético-lógica
La unidad aritmética y lógica o ALU es un circuito combinacional capaz de realizar
operaciones aritméticas y lógicas con números enteros y también con números reales. Las
operaciones que puede efectuar vienen definidas por el conjunto de instrucciones aritméticas
y lógicas de las que dispone el juego de instrucciones del computador.
Los operandos ingresan primero en código alfanumérico para luego convertirse a alguno de
estos convenios.
Es el formato más simple para representar números enteros positivos, expresados como una
secuencia de dígitos binarios: Xn-1;Xn-2;....X2; X1;X0
Como este formato solo permite números sin signo, para la representación de un número se
utiliza la totalidad de bits del formato. |------ n bits---------| n bits de magnitud
El rango de variabilidad para un número x en este formato es: 0<, ×<. 2n - 1
donde "n" es la cantidad de dígitos que componen el número; también se la conoce como tipo
de dato "ordinal sin signo”.
Por ejemplo, para un formato de n = 3 bits, el rango de variabilidad estará comprendido entre
0 y 7. Expresado de otra manera, permite representar los números comprendidos en ese
rango, como se observa en la recta de representación siguiente:
|----|----|----|----|-----|----|-----|---
0 1 2 3 4 5 6 7
Es igual al formato anterior, pero reserva el bit de extrema izquierda para el signo, de manera
que si ese bit es igual a 0, indicará que el número es positivo; asimismo, si, por el contrario, es
igual a 1, indicará que el número es negativo. A este tipo de representación también se la
llama "magnitud con signo”.
Nótese que perdemos aquí un bit de datos para utilizarlo como indicador de signo.
Coma o punto fijo con signo con negativos complementados a “2” (enteros)
Es igual al formato anterior, reservando el bit de extrema izquierda para el signo, de manera
que si ese bit es igual a 0, indicará que el número es positivo; por el contrario, si ese bit es
igual a 1, indicará que el número es negativo. La diferencia radica en que los n -1 bits
restantes se representan con su magnitud binaria real para el caso de los positivos y en el
complemento a la base de la magnitud para el caso de los negativos.
|------------ n bits-------------| |BS| n-1 bits de magnitud
El rango de variabilidad para los binarios con signo en complemento a la base es:
los números se representan considerando dos partes. La primera indica los bits que
representan al número y se llama mantisa, la otra indica la posición del punto dentro del
número y se llama exponente.
Esta manera de tratar números fraccionarios tiene cierta semejanza con lo que se conoce en
matemática como notación científica o exponencial.
Este nuevo formato de números se conoce como binarios de punto (coma) flotante, ya que el
punto varía su posición ("flota”) según el contenido binario de la entidad exponente.
La representación de datos en punto flotante incrementa el rango de números más allá de los
límites físicos de los registros. Por ejemplo, se sabe que en un registro de 16 bits el positivo
mayor definido como entero signado que se puede representar es el +32767. Si se considera
el registro dividido en partes iguales, 8 bits para la mantisa entera y 8 bits para el exponente,
el entero mayor se calcula según la fórmula siguiente:
Dado que los registros que operen estos datos tendrán una longitud fija, se asume un formato
de “m” bits para la mantisa y "p” bits para el exponente, entonces se puede definir el rango de
representación de números reales, que es siempre finito. O sea que determinados reales son
“representables” en el formato y otros quedan "afuera” de él.
Cuando el resultado de una operación supera los límites mayores definidos por el rango,
entonces es incorrecto. El error se conoce como overflow de resultado y actualiza un bit
(flag de overflow) en un registro asociado a la ALU, conocido como registro de estado o status
register.
Buses internos
Es importante saber que los procesadores actuales van reemplazando el tradicional FSB o
bus frontal local, el cual servía para comunicar el CPU con el resto de elementos de la placa
base,
Esto se debe a que el propio bus se ha introducido dentro de la CPU como una unidad de
administración de datos de entrada y salida (I/O) que comunica directamente la memoria RAM
con el procesador como si del antiguo puente norte se tratase. Tecnologías como
HyperTransport de AMD o HyperThreading de Intel se encargan de gestionar el intercambio
de información en los procesadores de alto rendimiento.
El BSB o Back Side Bus es el bus que se encarga de conectar el microprocesador con su
propia memoria caché, normalmente la de L2. De esta forma, se puede liberar el bus frontal
de bastante carga, y así acercar aún más la velocidad de las memorias caché a la velocidad
del núcleo.
Los multiplicadores, que son una serie de elementos ubicados dentro o fuera del procesador
que se encargan de medir la relación entre el reloj de la CPU y el reloj de los buses externos...
Gracias a estos multiplicadores, es posible que la frecuencia de la CPU sea muchísimo más
rápida que los buses externos, para así ser capaz de procesar más datos. Un multiplicador de
x10 por ejemplo, permitirá que un sistema que trabaje a 200 MHz lo haga en la CPU a 2000
MHz. En los procesadores actuales, podemos encontrar unidades con el multiplicador
desbloqueado; esto significa que podremos aumentar su frecuencia y así su velocidad de
procesamiento. A esto le llamamos overclocking.
La unidad de control
El ciclo de instrucciones y la unidad de control
Es la secuencia de operaciones que se hace para ejecutar cada una de las instrucciones. Lo
dividimos en cuatro fases principales:
1. Lectura de la instrucción.
4. Comprobación de interrupciones.
Las fases principales del ciclo de ejecución son comunes a la mayoría de los computadores
actuales y las diferencias principales se encuentran en el orden en el que se realizan algunas
de las operaciones de cada fase o en el que se realizan algunas de las operaciones en otras
fases. En cada fase se incluyen una o varias operaciones que hay que hacer. Para llevar a
cabo estas operaciones, nombradas microoperaciones, es necesaria una compleja gestión de
las señales de control y de la disponibilidad de los diferentes elementos del procesador, tarea
realizada por la unidad de control.
Veamos las operaciones principales que se realizan habitualmente en cada una de las cinco
fases del ciclo de ejecución de las instrucciones:
Las operaciones de esta fase son comunes a los diferentes tipos de instrucciones que
encontramos en el juego de instrucciones.
Esta fase se debe repetir para todos los operandos fuente que tenga la instrucción. Las
operaciones que hay que realizar en esta fase dependen del modo de direccionamiento que
tengan los operandos: para los más simples, como el inmediato o el directo a registro, no hay
que hacer ninguna operación; para los indirectos o los relativos, hay que hacer cálculos y
accesos a memoria. Si el operando fuente es implícito, vamos a buscar el dato en el lugar
predeterminado por aquella instrucción.
Las operaciones que hay que realizar en esta fase dependen del código de operación de la
instrucción y del modo de direccionamiento que tenga el operando destino.
Ejecución de la instrucción: las operaciones que se llevan a cabo son diferentes para
cada código de operación. Durante la ejecución, además de obtener el resultado de la
ejecución de la instrucción, se pueden modificar los bits de resultado de la palabra de
estado del procesador.
Esta fase, actualmente, está presente en todos los computadores, ya que todos utilizan E/S
para interrupciones y E/S para DMA.
Estrategias de segmentación
La segmentación es como una cadena de montaje. En cada etapa de la cadena se lleva a
cabo una parte del trabajo total y cuando se acaba el trabajo de una etapa, el producto pasa a
la siguiente y así sucesivamente hasta llegar al final. Si hay N etapas, se puede trabajar sobre
N productos al mismo tiempo y, si la cadena está bien equilibrada, saldrá un producto
acabado en el tiempo que se tarda en llevar a cabo una de las etapas. De esta manera, no se
reduce el tiempo que se tarda en hacer un producto, sino que se reduce el tiempo total
necesario para hacer una determinada cantidad de productos porque las operaciones de cada
etapa se efectúan simultáneamente.
Si consideramos que el producto es una instrucción y las etapas son cada una de las fases de
ejecución de la instrucción, que llamamos etapa de segmentación, hemos identificado los
elementos y el funcionamiento de la segmentación. Son necesarias nueve etapas para
ejecutar las tres instrucciones.
Son necesarias cinco etapas para ejecutar las tres instrucciones. Se ha reducido el tiempo
total que se tarda en ejecutar las tres instrucciones, pero no el tiempo que se tarda en ejecutar
cada una de las instrucciones. Si se quiere implementar la segmentación para mejorar el
rendimiento de un procesador, hay que tener en cuenta algunas cuestiones que implicarán
cambios en el diseño del procesador.
La unidad de control
La unidad de control se puede considerar el cerebro del computador. Está conectada al resto
de los componentes del computador mediante las señales de control. Es muy importante que
un computador tenga unidades funcionales muy eficientes y rápidas, pero si no se coordinan y
no se controlan correctamente, es imposible aprovechar todas las potencialidades que se
habían previsto en el diseño.
Modos de direccionamiento:
Si el dato está en la instrucción misma, no hay que hacer nada porque ya lo tenemos
en la misma instrucción. Se llama direccionamiento inmediato.
Si el dato está en un registro, no hay que hacer nada porque ya lo tenemos disponible
en un registro dentro del procesador. Se llama direccionamiento directo.
Cada microoperación hace una tarea determinada dentro del ciclo de ejecución de una
instrucción. A pesar de la simplicidad de estas microoperaciones, llevarlas a cabo implica la
activación de un conjunto de señales de control.
Una señal de control como una línea física que sale de la unidad de control y va hacia uno o
más dispositivos del computador por los que circula una señal eléctrica que representa un
valor lógico 0 o 1 y según cuáles sean los dispositivos a los que está conectado, es activo por
flanco o por nivel.
Figura 4: UC cableada
La representación del conjunto de todas las señales de control (combinación de ceros y unos)
da lugar a lo que denominamos palabra de control.
Figura 5: Microinstrucción
El inconveniente de este último tipo es que hace falta un decodificador para traducir los
códigos que aparecen en la microinstrucción de señales de control individuales. El conjunto de
microinstrucciones necesarias para ejecutar una instrucción da lugar a un microprograma
(microcódigo o firmware). Como cada instrucción realiza tareas diferentes, es necesario un
microprograma diferente para cada instrucción del juego de instrucciones de la arquitectura.
La memoria caché
Existe una jerarquía de memorias y que esta responde, a 3 factores:
Como lo muestra la figura 3, es claro que no solo existen memorias caché entre las diferentes
partes del procesador, sino que también se han desarrollado implementaciones de memorias
caché dentro del propio procesador, como una manera indirecta de incrementar la velocidad
de procesamiento, sin tocar la frecuencia de los ciclos de clock, o la ejecución de las
instrucciones.
La memoria caché de los procesadores actuales está integrada a la pastilla del procesador y
se puede dividir en tres niveles, L1, L2 y L3:
Caché de nivel 1 (L1): es la más pequeña después de los registros, y la más rápida de
las tres. Cada núcleo de procesamiento tiene su propia caché L1, que, a su vez, está
dividida en dos, la L1 Data, que se encarga de almacenar los datos, y la L1 Instruction,
que almacena las instrucciones a llevar a cabo. Suele ser de 32 KB cada una de ellas.
Caché de nivel 2 (L2): esta memoria es más lenta que la L1, aunque también más
grande. Normalmente, cada núcleo tiene su propia L2, que puede ser de unos 256 KB,
pero, en este caso, no está integrada directamente en el circuito del núcleo.
Caché de nivel 3 (L3): es la más lenta de las tres, aunque mucho más rápida que la
memoria RAM. También está situada fuera de los núcleos y está repartida entre varios
núcleos. Oscila entre los 8 MB y los 16 MB, aunque en CPU muy potentes alcanza
hasta 30 MB.
Organización de la caché
La memoria caché tiene un tiempo de acceso inferior al de la memoria principal con el objetivo
de reducir el tiempo de acceso medio a los datos, pero también tiene un tamaño mucho más
reducido que la memoria principal. Si un dato está en la memoria caché, es posible
proporcionarlo al procesador sin acceder a la memoria principal; si no, primero se lleva el dato
de la memoria principal a la memoria caché y después se proporciona el dato al procesador.
Si, en la mayoría de los accesos a memoria, el dato está en la memoria caché, el tiempo de
acceso medio será próximo al tiempo de acceso a la memoria caché. Eso es factible gracias a
la característica de proximidad referencial de los programas. Para trabajar con memoria
caché, la memoria principal se organiza en bloques de palabras, de manera que cuando hay
que trasladar datos de la memoria principal a la memoria caché se lleva un bloque entero de
palabras de memoria, no se trabaja con palabras individuales.
Cada vez que el procesador quiere acceder a una palabra de memoria, primero se accede a la
memoria caché; si la palabra de memoria se encuentra almacenada en la memoria caché, se
proporciona al procesador y diremos que se ha producido un acierto. En caso contrario, se
lleva el bloque de datos de la memoria principal que contiene la palabra de memoria hacia la
memoria caché y, cuando la palabra ya está en la memoria caché, se proporciona al
procesador; en este caso, diremos que se ha producido un fallo.
Cuando hay un fallo, el hardware de la memoria caché debe realizar la secuencia de tareas
siguiente:
1. Solicitar a la memoria principal el bloque donde está el dato que ha producido el fallo.
Un acceso con fallo en la memoria caché puede ser bastante más costoso en tiempo que un
acceso con acierto, por lo que es muy importante tener un número reducido de fallos. A partir
del concepto de acierto y fallo se definen los parámetros que utilizaremos para evaluar el
rendimiento de una memoria caché: tasa de fallos y tiempo medio de acceso.
Uno de los objetivos del diseño del sistema de memoria es obtener una tasa de fallos tan baja
como sea posible. Generalmente, se espera que sea inferior al 10 %. Se puede calcular
también el tiempo medio de acceso tm a partir de la tasa de fallos y de la tasa de aciertos,
conociendo el tiempo de acceso en caso de aciertos te y el tiempo de acceso en caso de
fallo tf, ya que el tiempo de fallo tiene en cuenta el tiempo necesario para llevar todo un bloque
de la memoria principal a la memoria caché y el tiempo de acceso al dato.
tm = Tf × tf + Te × te = Tf × tf + (1 – Tf) × te = Tf × (tf – te) + te
Si la tasa de fallos es cero, el tiempo medio de acceso a memoria es igual al tiempo de acceso
a la memoria caché.
Líneas de caché
La memoria caché también se organiza en bloques que se denominan líneas. Cada línea está
formada por un conjunto de palabras (el mismo número de palabras que tenga un bloque de
memoria principal), más una etiqueta compuesta por unos cuantos bits. El contenido de la
etiqueta permitirá saber qué bloque de la memoria principal se encuentra en cada línea de la
memoria caché en un momento dado.
El tamaño de la línea es de unos cuantos bytes de información (un tamaño habitual está entre
los 32 bytes y 128 bytes). Aumentar el tamaño de la línea permite aprovechar la localidad
espacial, pero hasta cierto punto. Cuando se produce un fallo, el tiempo necesario para
trasladar una línea más grande aumenta; además, disminuye el número de líneas disponibles
de la memoria caché (el tamaño de la memoria caché es fijo) y tendremos más competencia
para conseguir un bloque, lo que hará que se saquen de la caché líneas que todavía no se
han utilizado en su totalidad y se reducirá el efecto de la localidad espacial, y todo ello puede
representar un aumento en la tasa de fallos.
Se definen tres políticas de asignación diferentes para almacenar datos dentro de una
memoria caché:
Algoritmos de sustitución
La memoria caché es un recurso escaso, deben utilizarse técnicas que permitan borrar
información actualmente almacenada para dar lugar a nuevos datos.
En caso de que se utilice una asignación directa, el proceso es simple, ya que, cuando un
nuevo dato desde un bloque de memoria debe ser copiado, el anterior que ocupe la misma
línea deberá ser eliminado previamente. En el caso de correspondencias asociativas, este
proceso no funciona y se deben utilizar algoritmos.
Se describen de manera general los algoritmos de reemplazo más comunes, pero se pueden
encontrar otros algoritmos o variantes de estos.
1. FIFO (first in first out). Para elegir la línea se utiliza una cola, de manera que la línea
que hace más tiempo que está almacenada en la memoria caché será la reemplazada.
Este algoritmo puede reducir el rendimiento de la memoria caché porque la línea que
se encuentra almacenada en la memoria caché desde hace más tiempo no tiene que
ser necesariamente la que se utilice menos. Se puede implementar fácilmente
utilizando técnicas de buffers circulares (o round-robin): cada vez que se debe sustituir
una línea se utiliza la línea del buffer siguiente, y cuando se llega a la última, se vuelve
a empezar desde el principio.
2. LFU (least frequently used). En este algoritmo se elige la línea que hemos utilizado
menos veces. Se puede implementar añadiendo un contador del número de accesos a
cada línea de la memoria caché.
3. LRU (least recently used). Este algoritmo elige la línea que hace más tiempo que no
se utiliza. Es el algoritmo más eficiente, pero el más difícil de implementar,
especialmente si hay que elegir entre muchas líneas. Se utiliza habitualmente en
memorias caché asociativas por conjuntos, con conjuntos pequeños de 2 o 4 líneas…
Políticas de escritura
Comentaremos diferentes políticas para gestionar las escrituras y mantener la coherencia
entre los datos de la memoria caché y la memoria principal:
Si hay que reemplazar una línea que ha sido modificada, primero es necesario copiar la línea
modificada a la memoria principal y, a continuación, llevar el nuevo bloque, lo que aumenta
significativamente el tiempo para acceder al dato.
Cuando se quiere hacer una escritura de una dirección que no está en la memoria caché, se
producirá un fallo; este fallo se puede tratar de diferentes maneras:
3. Llevar el bloque a la memoria caché y escribir solo en la caché. Esta técnica se utiliza
habitualmente en escritura aplazada.
Existen dos tipos de conjuntos de instrucciones que los procesadores aplican para llevar a
cabo el procesamiento de la información: aquellos procesadores llamados CISC (Complex
Instruction Set Computer) y los llamados RISC (Reduced Instruction Set Computer).
La decisión de utilización de alguna de estas arquitecturas puede darse por dos razones:
Procesadores CISC
Los procesadores CISC poseen un set de instrucciones que se destaca por ser amplio y
permitir un procesamiento complejo entre operandos situados en la memoria o en los registros
internos, en contraposición a la arquitectura RISC
Otra característica es que, para ejecutar una sola instrucción, un chip CISC puede necesitar
entre tres y nueve ciclos de reloj.
Características de los procesadores CISC son:
Los compiladores son mucho más sencillos y rápidos. Por lo tanto, el debug y los
errores de programación son menores.
Procesadores RISC
Los procesadores RISC marcan la tendencia actual de construcción de microprocesadores.
RISC se ha convertido en una filosofía de diseño de CPU que se orienta a conjuntos de
instrucciones pequeñas y simples, que toman menor tiempo para ejecutarse .
Mientras que una PC, notebook o servidor con arquitectura x86 puede consumir una potencia
de entre 65 y 300 W, dependiendo de la aplicación y la fase del ciclo (estable o pico), un
procesador ARM puede rondar los 5 hasta 150 W en las mismas condiciones. Es por ello que
Intel y AMD optan por núcleos complejos de gran escala; en cambio, ARM parte con la ventaja
de la simplicidad, y con ello, el tamaño de los núcleos se reduce considerablemente frente a
sus rivales y así se puede meter un mayor número de aquellos, aunque sean más lentos y a
menor velocidad promedio, logrando que las cargas de trabajo se dividan y se puedan
optimizar más en ciertos entornos, como los servidores
En resumen, “los procesadores actuales no son completamente CISC o RISC. Los nuevos
diseños de una familia de procesadores con características típicamente CISC incorporan
características RISC, de la misma manera que las familias con características típicamente
RISC incorporan características CISC