Cuando estudiaba en la universidad, a menudo escuchaba la idea de que los compiladores de Fortran producían un código más rápido que los compiladores de C para un programa equivalente.
El razonamiento clave fue el siguiente: un compilador Fortran emite en promedio 1,1 instrucciones de procesador por línea de código, mientras que un compilador C emite en promedio 1,6 instrucciones de procesador por línea de código : no recuerdo los números exactos, pero el La idea era que los compiladores de C emitían notablemente más código de máquina y, por lo tanto, producían programas más lentos.
¿Qué tan válida es esa comparación? ¿Podemos decir que los compiladores de Fortran producen programas más rápidos que los compiladores de C o viceversa y por qué existe esta diferencia?
fuente
Respuestas:
IIRC, una de las principales razones por las que se dice que Fortran es más rápido es la ausencia de alias de puntero , por lo que pueden usar optimizaciones que los compiladores de C no pueden usar:
Pero estoy de acuerdo con otros aquí: comparar la cantidad promedio de instrucciones de ensamblador generadas para una línea de código es una tontería. Por ejemplo, un núcleo x86 moderno puede ejecutar dos instrucciones en paralelo si no acceden a los mismos registros. Por lo tanto, puede (en teoría) obtener un aumento del rendimiento del 100% para el mismo conjunto de instrucciones con solo reordenarlas . Los buenos compiladores a menudo también generarán más instrucciones de ensamblaje para obtener un código más rápido (piense en el desenrollado del bucle, en línea). El número total de instrucciones del ensamblador dice muy poco sobre el rendimiento de un fragmento de código.
fuente
restrict
palabra clave de C permite que el autor de una función especifique que un puntero no tiene alias. ¿Es esto suficiente para abordar la diferencia, o hay más?Comparación completamente inválida.
Primero, como señala @ Péter Török, primero debe comparar el número de líneas en programas equivalentes de Fortran y C para que esto sea una comparación válida en el número de líneas producidas.
Segundo, menos líneas de código no siempre equivalen a programas más rápidos . No todas las instrucciones de la máquina requieren la misma cantidad de ciclos para ejecutarse , pero también tiene otros problemas, como el acceso a la memoria , el almacenamiento en caché , etc.
Además de eso, las ejecuciones de código largas pueden ser más rápidas ya que da como resultado un número menor de líneas de ejecución (es decir, ¡Recuento de líneas! = Recuento de líneas ejecutadas ).
fuente
Dan tiene razón, los programas más largos no significan programas más lentos. Depende mucho de lo que estén haciendo.
No soy un experto en Fortran, lo sé un poco. Comparándolos, creo que una C bien escrita funcionaría mucho mejor con estructuras de datos y funcionalidades más complejas que Fortran. Alguien (por favor) corríjame si me equivoco aquí, pero creo que Fortran está en un "nivel más bajo" que C. Si es así, estoy seguro de que algunos problemas saldrían más rápido en Fortran.
Otra cosa, a primera vista, pensé que estabas preguntando si los compiladores son más rápidos. De hecho, creo que Fortran generalmente compilará más rápido para cantidades similares de código, pero el programa resultante y su funcionamiento sería una historia diferente. Es más sencillo analizarlo.
fuente
Creo que parte de esto es que los compiladores FORTRAN están diseñados para hacer algunos tipos de matemática muy rápido. Es por eso que las personas usan FORTRAN, para hacer cálculos lo más rápido posible
fuente
La declaración puede haber sido cierta en los viejos tiempos (alrededor de finales de los 70) cuando C estaba en su infancia, y Fortran fue respaldado por todos los principales fabricantes y estaba altamente optimizado. Los primeros Fortrans se basaban en la arquitectura de IBM, por lo que cosas tan simples como la aritmética habrían sido una declaración por instrucción de ensamblaje. Esto es cierto para las máquinas más antiguas como Data General y Prime, que tenían saltos de 3 vías. Esto no funciona en conjuntos de instrucciones modernos que no tienen un salto de 3 vías.
Las líneas de código no son iguales a las declaraciones de código. Las versiones anteriores de Fortran solo permitían una declaración por línea. Las versiones posteriores de Fortran pueden tomar múltiples declaraciones por línea. C puede tener múltiples declaraciones por línea. En los compiladores de producción más rápidos como el IVF de Intel (anteriormente CVF, MS Powerstation) y el C de Intel, realmente no hay diferencia entre los dos. Estos compiladores están altamente optimizados.
fuente
FORTRAN de estilo antiguo requería que un programador que quisiera poner a disposición de una función parte de una matriz necesitaba pasar una referencia a toda la matriz, junto con uno o más valores enteros que especificaran el subíndice inicial y el subíndice final o el número de elementos . C hace posible simplificar esto al pasar un puntero al inicio de la parte de interés junto con el número de elementos. En términos directos, esto aceleraría las cosas (pasar dos cosas en lugar de tres). Sin embargo, indirectamente, puede terminar ralentizando las cosas al limitar los tipos de optimización que puede realizar un compilador.
Considere la función:
Si un compilador supiera que cada uno de los punteros identificaría el inicio de una matriz, podría generar código que actuaría sobre los elementos de la matriz en paralelo, o en cualquier orden, ya que para cualquier operación x! = y, en dest [x ] no afectará a src1 [y] ni a src2 [y]. Por ejemplo, en algunos sistemas un compilador puede beneficiarse de generar código equivalente a:
Tenga en cuenta que cada operación que carga o calcula un valor tiene al menos una operación más entre él y la siguiente operación que usa ese valor. Algunos procesadores pueden superponer el procesamiento de diferentes operaciones cuando se cumplen tales condiciones, mejorando así el rendimiento. Sin embargo, tenga en cuenta que debido a que un compilador de C no tiene forma de saber que el código no se pasará a punteros a regiones parcialmente superpuestas de una matriz común, un compilador de C no puede realizar la transformación anterior. Los compiladores de FORTRAN a los que se les dio un código equivalente, sin embargo, pudieron hacer una transformación.
Si bien un programador en C podría intentar lograr un rendimiento comparable escribiendo explícitamente el código que desenrollaba el ciclo y superponía las operaciones de los pases adyacentes, dicho código podría degradar fácilmente el rendimiento si utilizara tantas variables automáticas que un compilador tuvo que "derramarlas" memoria. El optimizador de un compilador FORTRAN probablemente sabría más que un programador acerca de qué formas de entrelazado producirían un rendimiento óptimo en un escenario dado, y esas decisiones a menudo son mejores para esos compiladores. Si bien C99 intentó mejorar la situación de C agregando un
restrict
calificador, eso solo se podría usar aquí sidest[]
fuera una matriz separada de ambossrc1[]
ysrc2[]
, o si el programador agregó versiones separadas del bucle para manejar los casos en los que tododest
era disjunto desrc1
ysrc2
, dóndesrc1[]
ydest
eran iguales ysrc2
eran disjuntos, dóndesrc2[]
ydest[]
eran iguales ysrc1
eran disjuntos, y dónde las tres matrices eran iguales. FORTRAN, por el contrario, podría manejar los cuatro casos sin dificultad utilizando el mismo código fuente y el mismo código de máquina.fuente