Когда я учился в университете, я часто слышал мысль о том, что компиляторы Фортрана производят более быстрый код, чем компиляторы Си для эквивалентной программы.
Основные рассуждения звучали так: компилятор Фортрана выдает в среднем по 1,1 инструкции процессора на строку кода, в то время как компилятор C выдает в среднем по 1,6 инструкции процессора на строку кода - я не помню точные цифры, но Идея заключалась в том, что компиляторы C генерировали заметно больше машинного кода и, следовательно, создавали более медленные программы.
Насколько обосновано такое сравнение? Можно ли сказать, что компиляторы Fortran производят более быстрые программы, чем компиляторы C или наоборот, и почему существует эта разница?
c
comparison
compiler
fortran
Sharptooth
источник
источник
Ответы:
Одна из главных причин того, почему Fortran считается более быстрым, - это отсутствие псевдонимов указателей , поэтому они могут использовать оптимизации, которые компиляторы C не могут использовать:
Но я согласен с другими здесь: сравнивать среднее количество инструкций ассемблера, сгенерированных для строки кода, - полная чушь. Например, современное ядро x86 может выполнять две инструкции параллельно, если они не обращаются к одним и тем же регистрам. Таким образом, вы можете (теоретически) повысить производительность на 100% для того же набора инструкций, просто переупорядочив их . Хорошие компиляторы также часто генерируют больше инструкций по сборке, чтобы получить более быстрый код (развернуть цикл, встроить). Общее количество инструкций ассемблера очень мало говорит о производительности фрагмента кода.
источник
restrict
Ключевое слово C позволяет автору функции указать, что указатель не имеет псевдонимов. Достаточно ли этого для устранения разницы или есть что-то большее?Полностью неверное сравнение.
Во-первых, как указывает @ Péter Török, вы должны сначала сравнить количество строк в эквивалентных программах от Fortran и C, чтобы это было даже допустимым сравнением количества произведенных строк.
Во-вторых, меньшее количество строк кода не всегда равно быстрым программам . Не все машинные инструкции выполняют одинаковое количество циклов , но у вас также есть другие проблемы, такие как доступ к памяти , кэширование и т. Д.
Кроме того, длинный код может выполняться быстрее, поскольку это приводит к меньшему количеству строк выполнения (т. Е. Line Count! = Executed Line Count ).
источник
Дэн прав, более длинные программы не означают более медленные программы. Это сильно зависит от того, что они делают.
Я не эксперт по Фортрану, я немного знаю. Сравнивая их, я бы подумал, что хорошо написанный C мог бы добиться гораздо большей производительности при более сложных структурах данных и функциональности, чем Fortran. Кто-то (пожалуйста) исправит меня, если я ошибаюсь, но я думаю, что Fortran находится на более низком уровне, чем C. Если это так, я уверен, что некоторые проблемы на Fortran возникнут быстрее.
Другое дело, на первый взгляд, я подумал, что вы спрашиваете, работают ли компиляторы быстрее. Я действительно думаю, что Fortran, как правило, будет компилироваться быстрее для схожих объемов кода, но итоговая программа и то, как она работает, будет другой историей. Проще разобрать.
источник
Я думаю, что отчасти это связано с тем, что компиляторы FORTRAN предназначены для очень быстрой математической обработки некоторых типов. Вот почему люди используют FORTRAN, чтобы делать вычисления как можно быстрее
источник
Это утверждение могло быть правдой в старые времена (примерно в конце 70-х годов), когда C был в зачаточном состоянии, и Fortran поддерживался всеми крупными производителями и был высоко оптимизирован. Ранние Fortrans были основаны на архитектуре IBM, поэтому такие простые вещи, как арифметика, были бы, конечно, одним утверждением на инструкцию по сборке. Это верно для более старых машин, таких как Data General и Prime, которые имели 3-х ходовые прыжки. Это не работает с современными наборами команд, которые не имеют 3-х ходового перехода.
Строки кода не равны утверждениям кода. Более ранние версии Fortran допускали только одно утверждение на строку. Более поздние версии Fortran могут принимать несколько операторов в строке. C может иметь несколько операторов в строке. На более быстрых производственных компиляторах, таких как Intel IVF (ранее CVF, MS Powerstation) и Intel C, разницы между ними действительно нет. Эти компиляторы высоко оптимизированы.
источник
FORTRAN старого стиля требовал, чтобы программисту, который хотел сделать часть массива доступной для функции, требовалось передать ссылку на весь массив вместе с одним или несколькими целочисленными значениями, указывающими начальный индекс и либо конечный индекс, либо количество элементов. , C позволяет упростить это, передав указатель на начало интересующей части вместе с количеством элементов. Прямо говоря, это ускорит процесс (пропуская две вещи, а не три). Однако косвенным образом это может привести к замедлению работы за счет ограничения видов оптимизации, которые может выполнять компилятор.
Рассмотрим функцию:
если бы компилятор знал, что каждый из указателей будет идентифицировать начало массива, он мог бы генерировать код, который будет воздействовать на элементы массива параллельно или в любом порядке, поскольку для любого x! = y выполняются операции с dest [x ] не повлияет на src1 [y] и src2 [y]. Например, в некоторых системах компилятор может получить выгоду от генерации кода, эквивалентного:
Обратите внимание, что каждая операция, которая загружает или вычисляет значение, имеет по крайней мере еще одну операцию между ним и следующей операцией, которая использует это значение. Некоторые процессоры могут перекрывать обработку различных операций при соблюдении таких условий, что повышает производительность. Обратите внимание, однако, что поскольку компилятор C не может знать, что код не будет передаваться указатели на частично перекрывающиеся области общего массива, компилятор C не может выполнить вышеуказанное преобразование. Однако компиляторы FORTRAN, имеющие эквивалентный код, могли и действительно осуществили такое преобразование.
В то время как программист на C мог бы попытаться достичь сопоставимой производительности, явно написав код, который развернул цикл и перекрыл операции смежных проходов, такой код мог бы легко снизить производительность, если бы он использовал так много автоматических переменных, что компилятор должен был «пролить» их на Память. Оптимизатор компилятора FORTRAN, скорее всего, будет знать больше, чем программист, о том, какие формы чередования дадут оптимальную производительность в данном сценарии, и такие решения часто лучше оставить таким компиляторам. В то время как C99 пытался несколько улучшить ситуацию с C, добавив
restrict
классификатор, он мог бы использоваться здесь только в том случае, если онdest[]
был отдельным массивом от обоихsrc1[]
иsrc2[]
, или если программист добавил отдельные версии цикла для обработки случаев, когда всеdest
было не разделеноsrc1
иsrc2
, гдеsrc1[]
иdest
были равны иsrc2
не пересекались, гдеsrc2[]
иdest[]
были равны иsrc1
не пересекались, и где все три массива были равны. В отличие от этого, FORTRAN может без проблем обрабатывать все четыре случая, используя один и тот же исходный код и один и тот же машинный код.источник