Comenzando con Pentium Pro (microarquitectura P6), Intel rediseñó sus microprocesadores y usó el núcleo RISC interno bajo las antiguas instrucciones CISC. Desde Pentium Pro, todas las instrucciones CISC se dividen en partes más pequeñas (uops) y luego las ejecuta el núcleo RISC.
Al principio, me quedó claro que Intel decidió ocultar la nueva arquitectura interna y obligar a los programadores a utilizar "shell CISC". Gracias a esta decisión, Intel pudo rediseñar completamente la arquitectura de microprocesadores sin romper la compatibilidad, es razonable.
Sin embargo, no entiendo una cosa, ¿por qué Intel todavía mantiene ocultas las instrucciones RISC internas durante tantos años? ¿Por qué no dejarían que los programadores usen instrucciones RISC como el antiguo conjunto de instrucciones CISC x86?
Si Intel mantiene la compatibilidad con versiones anteriores durante tanto tiempo (todavía tenemos el modo 8086 virtual junto al modo de 64 bits), ¿por qué no nos permiten compilar programas para que omitan las instrucciones CISC y usen el núcleo RISC directamente? Esto abrirá una forma natural de abandonar lentamente el conjunto de instrucciones x86, que está en desuso hoy en día (esta es la razón principal por la que Intel decidió usar el núcleo RISC en el interior, ¿verdad?).
Mirando la nueva serie Intel 'Core i', veo que solo extienden el conjunto de instrucciones CISC agregando AVX, SSE4 y otros.
fuente
Respuestas:
No, el conjunto de instrucciones x86 ciertamente no está en desuso. Es tan popular como siempre. La razón por la que Intel utiliza internamente un conjunto de microinstrucciones similares a RISC es porque pueden procesarse de manera más eficiente.
Entonces, una CPU x86 funciona con un decodificador bastante resistente en la interfaz, que acepta instrucciones x86 y las convierte a un formato interno optimizado, que el backend puede procesar.
En cuanto a exponer este formato a programas "externos", hay dos puntos:
Esta no es una disposición perfecta, pero el costo es bastante pequeño y es una opción mucho mejor que diseñar la CPU para admitir dos conjuntos de instrucciones completamente diferentes. (En ese caso, probablemente terminarían inventando un tercer conjunto de microoperaciones para uso interno, solo porque se pueden ajustar libremente para adaptarse mejor a la arquitectura interna de la CPU)
fuente
La verdadera respuesta es simple.
El factor principal detrás de la implementación de procesadores RISC fue reducir la complejidad y ganar velocidad. La desventaja de RISC es la densidad de instrucción reducida, lo que significa que el mismo código expresado en formato similar a RISC necesita más instrucciones que el código CISC equivalente.
Este efecto secundario no significa mucho si su CPU funciona a la misma velocidad que la memoria, o al menos si ambas funcionan a velocidades razonablemente similares.
Actualmente, la velocidad de la memoria en comparación con la velocidad de la CPU muestra una gran diferencia en los relojes. Las CPU actuales son a veces cinco veces más rápidas que la memoria principal.
Este estado de la tecnología favorece un código más denso, algo que proporciona CISC.
Puede argumentar que los cachés podrían acelerar las CPU RISC. Pero lo mismo puede decirse de los cpus CISC.
Obtiene una mejora de velocidad mayor utilizando CISC y cachés que RISC y cachés, porque el mismo tamaño de caché tiene más efecto en el código de alta densidad que proporciona CISC.
Otro efecto secundario es que RISC es más difícil en la implementación del compilador. Es más fácil optimizar los compiladores para cpus CISC. etc.
Intel sabe lo que están haciendo.
Esto es tan cierto que ARM tiene un modo de densidad de código más alto llamado Thumb.
fuente
Necesita mirar el ángulo comercial de esto. Intel realmente ha intentado alejarse de x86, pero es la gallina de los huevos de oro para la empresa. XScale e Itanium nunca se acercaron al nivel de éxito que tiene su negocio principal x86.
Lo que básicamente estás pidiendo es que Intel se corte las venas a cambio de cálidos comentarios de los desarrolladores. Socavar x86 no les conviene. Cualquier cosa que haga que más desarrolladores no tengan que elegir apuntar a x86 socava x86. Eso, a su vez, los socava.
fuente
La respuesta es simple. ¡Intel no está desarrollando CPU para desarrolladores ! Los están desarrollando para las personas que toman las decisiones de compra , lo cual, por cierto, es lo que hacen todas las empresas del mundo.
Intel hace mucho tiempo se comprometió a que, (dentro de lo razonable, por supuesto), sus CPU seguirían siendo compatibles con versiones anteriores. La gente quiere saber que, cuando compran una nueva computadora basada en Intel, todos su software actual funcionará exactamente igual que en su computadora anterior. (¡Aunque, con suerte, más rápido!)
Además, Intel sabe exactamente lo importante que es ese compromiso, porque una vez intentaron tomar un camino diferente. Exactamente cuántas personas no se sabe con una CPU Itanium?!?
Puede que no le guste, pero esa decisión, permanecer con el x86, es lo que convirtió a Intel en uno de los nombres comerciales más reconocidos del mundo.
fuente
La respuesta de @ jalf cubre la mayoría de las razones, pero hay un detalle interesante que no menciona: el núcleo interno similar a RISC no está diseñado para ejecutar un conjunto de instrucciones como ARM / PPC / MIPS. El impuesto x86 no solo se paga en los decodificadores que consumen mucha energía, sino hasta cierto punto en todo el núcleo. es decir, no se trata solo de la codificación de instrucciones x86; es cada instrucción con una semántica extraña.
Supongamos que Intel creó un modo de funcionamiento en el que el flujo de instrucciones era diferente a x86, con instrucciones que se asignaban más directamente a uops. Supongamos también que cada modelo de CPU tiene su propio ISA para este modo, por lo que todavía son libres de cambiar los componentes internos cuando lo deseen y exponerlos con una cantidad mínima de transistores para la decodificación de instrucciones de este formato alternativo.
Presumiblemente, todavía tendría la misma cantidad de registros, asignados al estado arquitectónico x86, por lo que los sistemas operativos x86 pueden guardarlo / restaurarlo en cambios de contexto sin usar el conjunto de instrucciones específicas de la CPU. Pero si descartamos esa limitación práctica, sí, podríamos tener algunos registros más porque podemos usar los registros temporales ocultos normalmente reservados para el microcódigo 1 .
Si solo tenemos decodificadores alternativos sin cambios en las etapas posteriores de la canalización (unidades de ejecución), este ISA todavía tendría muchas excentricidades x86. No sería una arquitectura RISC muy agradable. Ninguna instrucción por sí sola sería muy compleja, pero algunas de las otras locuras de x86 seguirían ahí.
Por ejemplo: los cambios a la izquierda / derecha dejan el indicador de desbordamiento sin definir, a menos que el recuento de cambios sea uno, en cuyo caso OF = la detección de desbordamiento con signo habitual. Locura similar para rota. Sin embargo, las instrucciones RISC expuestas podrían proporcionar cambios sin banderas y así sucesivamente (permitiendo el uso de solo uno o dos de los múltiples uops que generalmente se incluyen en algunas instrucciones x86 complejas). Así que esto realmente no se sostiene como el principal contraargumento.
Si va a hacer un decodificador completamente nuevo para un RISC ISA, puede hacer que elija partes de las instrucciones x86 para exponerlas como instrucciones RISC. Esto mitiga un poco la especialización x86 del núcleo.
La codificación de la instrucción probablemente no sea de tamaño fijo, ya que las uops individuales pueden contener una gran cantidad de datos. Muchos más datos de los que tienen sentido si todos los insns son del mismo tamaño. Una sola uop microfundida puede agregar un operando inmediato de 32 bits y un operando de memoria que usa un modo de direccionamiento con 2 registros y un desplazamiento de 32 bits. (En SnB y versiones posteriores, solo los modos de direccionamiento de registro único pueden microfusarse con operaciones ALU).
Los uops son muy grandes y no muy similares a las instrucciones ARM de ancho fijo. Un conjunto de instrucciones de 32 bits de ancho fijo solo puede cargar inmediatos de 16 bits a la vez, por lo que cargar una dirección de 32 bits requiere un par carga-media baja-inmediata / carga alta-inmediata. x86 no tiene que hacer eso, lo que ayuda a que no sea terrible con solo 15 registros GP que limitan la capacidad de mantener constantes en los registros. (15 es una gran ayuda sobre 7 registros, pero duplicar nuevamente a 31 ayuda mucho menos, creo que se encontró algo de simulación. RSP generalmente no es de propósito general, por lo que es más como 15 registros GP y una pila).
TL; resumen de DR:
De todos modos, esta respuesta se reduce a "el conjunto de instrucciones x86 es probablemente la mejor manera de programar una CPU que debe poder ejecutar instrucciones x86 rápidamente", pero es de esperar que arroje algo de luz sobre las razones.
Formatos de uop internos en el front-end frente al back-end
Consulte también los modos de micro fusión y direccionamiento para ver un caso de diferencias en lo que pueden representar los formatos uop de front-end y back-end en las CPU Intel.
Nota al pie 1 : Hay algunos registros "ocultos" para su uso como temporales por microcódigo. Estos registros se renombran al igual que los registros arquitectónicos x86, por lo que las instrucciones multi-uop pueden ejecutarse fuera de orden.
por ejemplo,
xchg eax, ecx
en las CPU de Intel se decodifica como 3 uops ( ¿por qué? ), y nuestra mejor suposición es que estos son uops tipo MOV que lo hacentmp = eax; ecx=eax ; eax=tmp;
. En ese orden, porque mido la latencia de la dirección dst-> src en ~ 1 ciclo, frente a 2 en el otro sentido. Y estos movimientos no son comomov
instrucciones regulares ; no parecen ser candidatos para la eliminación de mov de latencia cero.Consulte también http://blog.stuffedcow.net/2013/05/measuring-rob-capacity/ para una mención de intentar medir experimentalmente el tamaño de PRF y tener que tener en cuenta los registros físicos utilizados para mantener el estado arquitectónico, incluidos los registros ocultos.
En el front-end después de los decodificadores, pero antes de la etapa de emisión / cambio de nombre que cambia el nombre de los registros al archivo de registro físico, el formato interno uop usa números de registro similares a los números de registro x86, pero con espacio para abordar estos registros ocultos.
El formato uop es algo diferente dentro del núcleo fuera de orden (ROB y RS), también conocido como back-end (después de la etapa de emisión / cambio de nombre). Los archivos de registro físico int / FP tienen cada uno 168 entradas en Haswell , por lo que cada campo de registro en un uop debe ser lo suficientemente amplio para abordar esa cantidad.
Dado que el renombrador está en el HW, probablemente sería mejor usarlo, en lugar de enviar instrucciones programadas estáticamente directamente al back-end. Así que podríamos trabajar con un conjunto de registros tan grande como los registros arquitectónicos x86 + temporales de microcódigo, no más que eso.
El back-end está diseñado para funcionar con un renombrador de front-end que evita los peligros WAW / WAR, por lo que no podríamos usarlo como una CPU en orden incluso si quisiéramos. No tiene enclavamientos para detectar esas dependencias; que se maneja por problema / cambio de nombre.
Sería bueno si pudiéramos alimentar uops en el back-end sin el cuello de botella de la etapa de emisión / cambio de nombre (el punto más estrecho en las tuberías modernas de Intel, por ejemplo, 4 de ancho en Skylake frente a 4 ALU + 2 carga + 1 puertos de almacenamiento en el back-end). Pero si hiciste eso, no creo que puedas programar estáticamente el código para evitar la reutilización de registros y pisar un resultado que aún es necesario si un error de caché detuvo una carga durante mucho tiempo.
Por lo tanto, necesitamos enviar uops a la etapa de emisión / cambio de nombre, probablemente solo omitiendo la decodificación, no el caché de uop o IDQ. Luego obtenemos un ejecutivo de OoO normal con una detección de peligros sensata. La tabla de asignación de registros solo está diseñada para cambiar el nombre de 16 + algunos registros enteros en el PRF entero de 168 entradas. No podíamos esperar que el HW cambiara el nombre de un conjunto mayor de registros lógicos en el mismo número de registros físicos; eso requeriría una RAT más grande.
fuente
Además de las respuestas anteriores, la otra razón es la segmentación del mercado. Se cree que algunas instrucciones se implementan en microcódigo en lugar de en hardware, por lo que permitir que cualquiera ejecute microoperaciones arbitrarias puede socavar las ventas de nuevos cpus con instrucciones CISC "nuevas" de mayor rendimiento.
fuente
SHL r/m32, cl
ha una dependencia de entrada en FLAGS y decodifica a 3 uops en Skylake. Sin embargo, solo fue 1 uop en Core2 / Nehalem, según las pruebas de Agner Fog).