El artículo de Wikipedia sobre EPIC ya describió los muchos peligros comunes a VLIW y EPIC.
Si alguien no capta la sensación de fatalismo de ese artículo, permítanme resaltar esto:
Las respuestas de carga de una jerarquía de memoria que incluye cachés de CPU y DRAM no tienen un retraso determinista.
En otras palabras, cualquier diseño de hardware que no pueda hacer frente a (*) la latencia no determinista del acceso a la memoria se convertirá en una falla espectacular.
(*) Al "hacer frente", es necesario lograr un rendimiento de ejecución razonablemente bueno (en otras palabras, "competitivo en costos"), lo que requiere no dejar que la CPU quede inactiva durante decenas a cientos de ciclos con tanta frecuencia.
Tenga en cuenta que la estrategia de afrontamiento empleada por EPIC (mencionada en el artículo de Wikipedia vinculado anteriormente) en realidad no resuelve el problema. Simplemente dice que la carga de indicar la dependencia de datos ahora recae en el compilador. Esta bien; el compilador ya tiene esa información, por lo que es sencillo para el compilador cumplirla. El problema es que la CPU seguirá inactiva durante decenas a cientos de ciclos a través de un acceso a memoria. En otras palabras, externaliza una responsabilidad secundaria, sin dejar de hacer frente a la responsabilidad primaria.
La pregunta puede reformularse como: "Dada una plataforma de hardware destinada a ser un fracaso, ¿por qué (1) no (2) no pudieron los escritores del compilador hacer un heroico esfuerzo para canjearla?"
Espero que mi reformulación haga obvia la respuesta a esa pregunta.
Hay un segundo aspecto del fracaso que también es fatal.
Las estrategias de afrontamiento (mencionadas en el mismo artículo) suponen que la captación previa basada en software se puede utilizar para recuperar al menos parte de la pérdida de rendimiento debido a la latencia no determinista del acceso a la memoria.
En realidad, la captación previa solo es rentable si realiza operaciones de transmisión (lectura de memoria de forma secuencial o altamente predecible).
(Dicho esto, si su código hace acceso frecuente a algunas áreas de memoria localizadas, el almacenamiento en caché ayudará).
Sin embargo, la mayoría del software de uso general debe hacer muchos accesos aleatorios a la memoria. Si consideramos los siguientes pasos:
- Calcule la dirección y luego
- Lea el valor y luego
- Úselo en algunos cálculos
Para la mayoría del software de propósito general, estos tres deben ejecutarse en rápida sucesión. En otras palabras, no siempre es posible (dentro de los límites de la lógica del software) calcular la dirección por adelantado, o encontrar suficiente trabajo para llenar los puestos entre estos tres pasos.
Para ayudar a explicar por qué no siempre es posible encontrar suficiente trabajo para llenar los puestos, así es como se puede visualizar.
- Digamos que para ocultar de manera efectiva los puestos, necesitamos completar 100 instrucciones que no dependen de la memoria (por lo que no sufrirán una latencia adicional).
- Ahora, como programador, cargue cualquier software de su elección en un desensamblador. Elija una función aleatoria para el análisis.
- ¿Puedes identificar en cualquier lugar una secuencia de 100 instrucciones (*) que estén exclusivamente libres de accesos a la memoria?
(*) Si alguna vez pudiéramos hacer NOP
un trabajo útil ...
Las CPU modernas intentan hacer frente a lo mismo utilizando información dinámica, al mismo tiempo que siguen el progreso de cada instrucción a medida que circulan por las tuberías. Como mencioné anteriormente, parte de esa información dinámica se debe a una latencia de memoria no determinista, por lo tanto, los compiladores no pueden predecirla con ningún grado de precisión. En general, simplemente no hay suficiente información disponible en el momento de la compilación para tomar decisiones que podrían llenar esos puestos.
En respuesta a la respuesta de AProgrammer
No es que "compilar ... extraer paralelismo es difícil".
El reordenamiento de la memoria y las instrucciones aritméticas por parte de los compiladores modernos es la evidencia de que no tiene problemas para identificar operaciones que son independientes y, por lo tanto, ejecutables simultáneamente.
El principal problema es que la latencia de memoria no determinista significa que cualquier "emparejamiento de instrucciones" que uno haya codificado para el procesador VLIW / EPIC terminará estancado por el acceso a la memoria.
La optimización de las instrucciones que no se bloquean (solo registro, aritmética) no ayudará con los problemas de rendimiento causados por instrucciones que es muy probable que se bloqueen (acceso a la memoria).
Es un ejemplo de no aplicar la regla de optimización 80-20: optimizar las cosas que ya son rápidas no mejorará significativamente el rendimiento general, a menos que las cosas más lentas también se optimicen.
En respuesta a la respuesta de Basile Starynkevitch
No es "... (lo que sea) es difícil", es que EPIC no es adecuado para ninguna plataforma que tenga que hacer frente a un alto dinamismo en latencia.
Por ejemplo, si un procesador tiene todo lo siguiente:
- Sin acceso directo a la memoria;
- Cualquier acceso a la memoria (lectura o escritura) debe programarse mediante transferencia DMA;
- Cada instrucción tiene la misma latencia de ejecución;
- Ejecución en orden;
- Unidades de ejecución amplias / vectorizadas;
Entonces VLIW / EPIC encajará bien.
¿Dónde se encuentran estos procesadores? DSP. Y aquí es donde ha florecido VLIW.
En retrospectiva, el fracaso de Itanium (y el continuo esfuerzo de I + D en un fracaso, a pesar de la evidencia obvia) es un ejemplo de fracaso organizacional y merece ser estudiado en profundidad.
Por supuesto, las otras empresas del proveedor, como hyperthreading, SIMD, etc., parecen tener mucho éxito. Es posible que la inversión en Itanium haya tenido un efecto enriquecedor en las habilidades de sus ingenieros, lo que les ha permitido crear la próxima generación de tecnología exitosa.