Quand j'étudiais à l'université, j'ai souvent entendu l'idée que les compilateurs Fortran produisaient du code plus rapide que les compilateurs C pour un programme équivalent.
Le raisonnement clé était le suivant: un compilateur Fortran émet en moyenne 1,1 instruction de processeur par ligne de code, tandis qu'un compilateur C émet en moyenne 1,6 instruction de processeur par ligne de code - je ne me souviens pas des chiffres exacts, mais le L'idée était que les compilateurs C émettaient sensiblement plus de code machine et produisaient donc des programmes plus lents.
Quelle est la validité d'une telle comparaison? Peut-on dire que les compilateurs Fortran produisent des programmes plus rapides que les compilateurs C ou vice versa et pourquoi cette différence existe-t-elle?
la source
Réponses:
L'IIRC, l'une des principales raisons pour lesquelles Fortran serait plus rapide, est l'absence d' alias de pointeur , afin qu'ils puissent utiliser des optimisations que les compilateurs C ne peuvent pas utiliser:
Mais je suis d'accord avec les autres ici: Comparer le nombre moyen d'instructions d'assembleur générées pour une ligne de code est un non-sens complet. Par exemple, un noyau x86 moderne peut exécuter deux instructions en parallèle s'il n'accède pas aux mêmes registres. Ainsi, vous pouvez (en théorie) obtenir une augmentation des performances de 100% pour le même ensemble d'instructions simplement en les réorganisant . Les bons compilateurs génèrent également souvent plus d' instructions d'assemblage pour obtenir un code plus rapide (pensez au déroulement de la boucle, en ligne). Le nombre total d'instructions de l'assembleur en dit très peu sur les performances d'un morceau de code.
la source
restrict
mot clé C permet à l'auteur d'une fonction de spécifier qu'un pointeur n'a pas d'alias. Est-ce suffisant pour combler la différence, ou y a-t-il plus?Comparaison complètement invalide.
Tout d'abord, comme le souligne @ Péter Török, vous devez d'abord comparer le nombre de lignes dans des programmes équivalents de Fortran et C pour que cela soit même une comparaison valide sur le nombre de lignes produites.
Deuxièmement, moins de lignes de code ne sont pas toujours égales à des programmes plus rapides . Toutes les instructions de la machine ne prennent pas le même nombre de cycles à exécuter , mais vous avez également d'autres problèmes tels que l' accès à la mémoire , la mise en cache , etc.
En plus de cela, les longues exécutions de code peuvent être plus rapides car elles entraînent un nombre inférieur de lignes d'exécution (c'est-à-dire, nombre de lignes ! = Nombre de lignes exécutées ).
la source
Dan a raison, des programmes plus longs ne signifient pas des programmes plus lents. Cela dépend beaucoup de ce qu'ils font.
Je ne suis pas un expert de Fortran, j'en sais un peu. En les comparant, je pense qu'un C bien écrit ferait beaucoup mieux en termes de performances avec des structures de données et des fonctionnalités plus complexes que Fortran. Quelqu'un (s'il vous plaît) corrigez-moi si je me trompe ici, mais je pense que Fortran est quelque peu à un «niveau inférieur» par rapport à C. Si c'est le cas, je suis sûr que certains problèmes pourraient survenir plus rapidement sur Fortran.
Une autre chose, à première vue, je pensais que vous demandiez si les compilateurs sont plus rapides. En fait, je pense que Fortran compilera généralement plus rapidement pour des quantités similaires de code, mais le programme résultant et son fonctionnement seraient une autre histoire. C'est juste plus simple à analyser.
la source
Je pense que cela tient en partie au fait que les compilateurs FORTRAN sont conçus pour effectuer certains types de calculs très rapidement. C'est pourquoi les gens utilisent FORTRAN, pour faire des calculs le plus rapidement possible
la source
La déclaration était peut-être vraie dans le passé (vers la fin des années 70) lorsque C était à ses balbutiements, et Fortran était pris en charge par tous les principaux fabricants et était hautement optimisé. Les premiers Fortrans étaient basés sur l'architecture IBM, des trucs aussi simples comme l'arithmétique auraient certainement été une instruction par instruction d'assemblage. Cela est vrai des machines plus anciennes comme Data General et Prime, qui avaient des sauts à 3 voies. Cela ne fonctionne pas sur les jeux d'instructions modernes qui n'ont pas de saut à 3 voies.
Les lignes de code ne correspondent pas aux déclarations de code. Les versions antérieures de Fortran ne permettaient qu'une seule instruction par ligne. Les versions ultérieures de Fortran peuvent accepter plusieurs instructions par ligne. C peut avoir plusieurs instructions par ligne. Sur les compilateurs de production plus rapides comme IVF d'Intel (anciennement CVF, MS Powerstation) et C d'Intel, il n'y a vraiment aucune différence entre les deux. Ces compilateurs sont hautement optimisés.
la source
FORTRAN à l'ancienne exigeait qu'un programmeur qui voulait mettre une partie d'un tableau à la disposition d'une fonction ait besoin de passer une référence à l'ensemble du tableau, ainsi qu'une ou plusieurs valeurs entières spécifiant l'indice de départ et soit l'indice de fin, soit le nombre d'éléments . C permet de simplifier cela en passant un pointeur sur le début de la portion d'intérêt avec le nombre d'éléments. En termes directs, cela accélérerait les choses (en passant deux choses plutôt que trois). Indirectement, cependant, cela peut finir par ralentir les choses en limitant les types d'optimisation qu'un compilateur peut effectuer.
Considérez la fonction:
si un compilateur savait que chacun des pointeurs identifierait le début d'un tableau, il pourrait générer du code qui agirait sur les éléments du tableau en parallèle ou dans n'importe quel ordre, car pour tout x! = y, les opérations sur dest [x ] n'affectera pas src1 [y] ni src2 [y]. Par exemple, sur certains systèmes, un compilateur peut bénéficier de la génération de code équivalent à:
Notez que chaque opération qui charge ou calcule une valeur a au moins une opération de plus entre elle et l'opération suivante qui utilise cette valeur. Certains processeurs peuvent chevaucher le traitement de différentes opérations lorsque ces conditions sont remplies, améliorant ainsi les performances. Notez cependant que, comme un compilateur C n'a aucun moyen de savoir que le code ne passera pas de pointeurs vers des régions se chevauchant partiellement d'un tableau commun, un compilateur C ne peut pas effectuer la transformation ci-dessus. Cependant, les compilateurs FORTRAN à code équivalent pouvaient et ont fait une telle transformation.
Alors qu'un programmeur C pourrait tenter d'obtenir des performances comparables en écrivant explicitement du code qui déroulait la boucle et chevauchait les opérations des passes adjacentes, un tel code pourrait facilement dégrader les performances s'il utilisait tant de variables automatiques qu'un compilateur devait les "renverser" sur Mémoire. L'optimiseur d'un compilateur FORTRAN en connaîtrait probablement plus qu'un programmeur sur les formes d'entrelacement qui fourniraient des performances optimales dans un scénario donné, et il est souvent préférable de laisser ces décisions à ces compilateurs. Alors que C99 tentait d'améliorer quelque peu la situation de C en ajoutant un
restrict
qualificatif, cela ne pouvait être utilisé ici que s'ildest[]
s'agissait d'un tableau distinct des deuxsrc1[]
etsrc2[]
, ou si le programmeur avait ajouté des versions distinctes de la boucle pour gérer les cas où toutdest
était disjoint desrc1
etsrc2
, oùsrc1[]
etdest
étaient égaux etsrc2
étaient disjoints, oùsrc2[]
etdest[]
étaient égaux etsrc1
étaient disjoints, et où les trois tableaux étaient égaux. FORTRAN, en revanche, pouvait gérer les quatre cas sans difficulté en utilisant le même code source et le même code machine.la source