Легче ли оптимизировать Fortran, чем C, для тяжелых вычислений? - PullRequest
388 голосов
/ 28 сентября 2008

Время от времени я читаю, что Fortran является или может быть быстрее C для тяжелых вычислений. Это действительно так? Я должен признать, что почти не знаю Фортрана, но код Фортрана, который я видел до сих пор, не показал, что у языка есть особенности, которых нет у C.

Если это правда, пожалуйста, скажите мне, почему. Пожалуйста, не говорите мне, какие языки или библиотеки хороши для обработки чисел, я не собираюсь писать приложение или библиотеку для этого, мне просто любопытно.

Ответы [ 23 ]

424 голосов
/ 28 сентября 2008

Языки имеют похожие наборы функций. Разница в производительности объясняется тем, что Fortran говорит, что использование псевдонимов недопустимо, если только не используется оператор EQUIVALENCE. Любой код, имеющий псевдонимы, не является допустимым Fortran, но это зависит от программиста, а не от компилятора для обнаружения этих ошибок. Таким образом, компиляторы Fortran игнорируют возможные псевдонимы указателей памяти и позволяют им генерировать более эффективный код. Взгляните на этот маленький пример в C:

void transform (float *output, float const * input, float const * matrix, int *n)
{
    int i;
    for (i=0; i<*n; i++)
    {
        float x = input[i*2+0];
        float y = input[i*2+1];
        output[i*2+0] = matrix[0] * x + matrix[1] * y;
        output[i*2+1] = matrix[2] * x + matrix[3] * y;
    }
}

Эта функция будет работать медленнее, чем аналог Фортрана после оптимизации. Почему так? Если вы записываете значения в выходной массив, вы можете изменить значения матрицы. В конце концов, указатели могут перекрываться и указывать на один и тот же кусок памяти (включая указатель int!). Компилятор C вынужден перезагружать четыре значения матрицы из памяти для всех вычислений.

В Фортране компилятор может загрузить значения матрицы один раз и сохранить их в регистрах. Это может быть сделано, потому что компилятор Фортрана предполагает, что указатели / массивы не перекрываются в памяти.

К счастью, ключевое слово restrict и строгое псевдонимы были введены в стандарт C99 для решения этой проблемы. Это хорошо поддерживается в большинстве компиляторов C ++ и в наши дни. Ключевое слово позволяет дать компилятору подсказку, что программист обещает, что указатель не совпадает с каким-либо другим указателем. Строгое-алиасинг означает, что программист обещает, что указатели другого типа никогда не будут перекрываться, например, double* не будет перекрываться с int* (с определенным исключением, что char* и void* могут перекрываться с чем угодно) .

Если вы используете их, вы получите одинаковую скорость от C и Fortran. Однако возможность использовать ключевое слово restrict только с функциями, критичными для производительности, означает, что программы на C (и C ++) намного безопаснее и их легче писать. Например, рассмотрим недопустимый код на Фортране: CALL TRANSFORM(A(1, 30), A(2, 31), A(3, 32), 30), который большинство компиляторов Фортрана с радостью компилирует без каких-либо предупреждений, но при этом возникает ошибка, которая появляется только на некоторых компиляторах, на некоторых аппаратных средствах и с некоторыми вариантами оптимизации.

155 голосов
/ 06 октября 2008

Да, в 1980 году; в 2008? зависит

Когда я начал профессионально программировать, доминирование в скорости на Фортране было просто проблемой. Я помню, как читал об этом в «Докторе Доббсе» и рассказывал старшим программистам о статье - они смеялись.

Итак, у меня есть два взгляда на это: теоретический и практический. Теоретически Сегодня Fortran не имеет внутреннего преимущества для C / C ++ или даже для любого языка, который допускает ассемблерный код. На практике Сегодня Fortran по-прежнему пользуется преимуществами наследия истории и культуры, построенного на оптимизации числового кода.

Вплоть до и включая Fortran 77 вопросы проектирования языка были в центре внимания оптимизации. Из-за состояния теории и технологии компилятора это часто означало ограничение функций и возможностей, чтобы дать компилятору лучшую возможность для оптимизации кода. Хорошая аналогия - думать о Fortran 77 как о профессиональной гоночной машине, которая жертвует характеристиками ради скорости. В наши дни компиляторы стали лучше на всех языках, а функции для повышения производительности программирования более ценны. Тем не менее, есть еще места, где люди в основном заинтересованы в скорости в научных вычислениях; эти люди, скорее всего, унаследовали код, обучение и культуру от людей, которые сами были программистами на Фортране.

Когда начинаешь говорить об оптимизации кода, возникает много проблем, и лучший способ понять это - скрываться там, где работают люди, для которых нужен быстрый числовой код . Но имейте в виду, что такой критически чувствительный код, как правило, составляет небольшую долю от общих строк кода и очень специализирован: большая часть кода на Фортране так же «неэффективна», как и большая часть кода на других языках, и оптимизация должна даже не будет главной проблемой такого кода .

Прекрасным местом для начала изучения истории и культуры Фортрана является Википедия. Запись в Фортран Википедии великолепна, и я очень ценю тех, кто потратил время и силы, чтобы сделать ее полезной для сообщества Фортран.

(Сокращенная версия этого ответа была бы комментарием в отличной ветке, начатой ​​ Nils , но у меня нет кармы, чтобы сделать это. На самом деле, я, вероятно, ничего бы не написал Во всяком случае, кроме этого, эта тема имеет фактическое информационное содержание и обмен информацией, в отличие от пламенных войн и языкового фанатизма, который является моим основным опытом в этой области. Я был ошеломлен и должен был поделиться любовью.)

60 голосов
/ 29 декабря 2008

В некоторой степени Fortran был разработан с учетом оптимизации компилятора. Язык поддерживает операции с целыми массивами, где компиляторы могут использовать параллелизм (особенно на многоядерных процессорах). Например,

Умножение плотной матрицы просто:

matmul(a,b)

L2 норма вектора x:

sqrt(sum(x**2))

Более того, такие инструкции, как FORALL, PURE & ELEMENTAL процедуры и т. Д., Помогают оптимизировать код. По этой простой причине даже указатели на Фортране не так гибки, как С.

Предстоящий стандарт Fortran (2008) имеет совместные массивы, которые позволяют легко писать параллельный код. G95 (с открытым исходным кодом) и компиляторы из CRAY уже поддерживают его.

Так что да, Fortran может быть быстрым просто потому, что компиляторы могут оптимизировать / распараллелить его лучше, чем C / C ++. Но опять же, как и все в жизни, есть хорошие и плохие компиляторы.

37 голосов
/ 30 октября 2011

Забавно, что здесь много ответов от незнания языков. Это особенно актуально для программистов на C / C ++, которые открыли старый код FORTRAN 77 и обсудили его слабые стороны.

Я полагаю, что проблема скорости - это в основном вопрос между C / C ++ и Fortran. В огромном коде это всегда зависит от программиста. Есть некоторые особенности языка, которые Фортран превосходит, и некоторые функции, которые делает С. Так что в 2011 году никто не может сказать, какой из них быстрее.

Что касается самого языка, Fortran в настоящее время поддерживает функции Full OOP и полностью обратно совместим. Я использовал Fortran 2003 полностью, и я бы сказал, что использовать его было просто восхитительно. В некоторых аспектах Fortran 2003 все еще отстает от C ++, но давайте посмотрим на его использование. Fortran в основном используется для численных вычислений, и никто не использует причудливые функции C ++ ООП по соображениям скорости. В высокопроизводительных вычислениях C ++ практически некуда деваться (взгляните на стандарт MPI, и вы увидите, что C ++ устарел!).

В настоящее время вы можете просто заниматься программированием на разных языках с помощью Fortran и C / C ++. Есть даже интерфейсы для GTK + в Фортране. Есть бесплатные компиляторы (gfortran, g95) и много отличных коммерческих.

28 голосов
/ 28 сентября 2008

Есть несколько причин, почему Фортран мог быть быстрее. Однако количество, которое они имеют значение, настолько незначительно или может быть обойдено в любом случае, что это не должно иметь значения. В настоящее время основной причиной использования Fortran является поддержка или расширение устаревших приложений.

  • ЧИСТЫЕ и ЭЛЕМЕНТАЛЬНЫЕ ключевые слова о функциях. Это функции, которые не имеют побочных эффектов. Это позволяет выполнять оптимизацию в определенных случаях, когда компилятор знает, что одна и та же функция будет вызываться с одинаковыми значениями. Примечание: GCC реализует «чистый» как расширение языка. Другие компиляторы могут также. Межмодульный анализ также может выполнить эту оптимизацию, но это сложно.

  • стандартный набор функций, которые работают с массивами, а не с отдельными элементами. Такие вещи, как sin (), log (), sqrt () принимают массивы вместо скаляров. Это облегчает оптимизацию рутины. Автоматическая векторизация дает те же преимущества в большинстве случаев, если эти функции встроены или встроены

  • Встроенный комплексный тип. Теоретически это может позволить компилятору переупорядочивать или исключать определенные инструкции в определенных случаях, но, скорее всего, вы увидите то же преимущество с struct {double re, im; }; идиома, используемая в C. Это ускоряет разработку, хотя операторы работают со сложными типами в фортран.

27 голосов
/ 28 сентября 2008

Я думаю, что ключевым моментом в пользу Fortran является то, что это язык, немного более подходящий для выражения математики на основе векторов и массивов. Упомянутая выше проблема анализа указателей является реальной на практике, поскольку переносимый код не может предположить, что вы можете что-то сказать компилятору. ВСЕГДА преимущество в вычислениях выражений заключается в том, что они ближе к тому, как выглядит домен. У C на самом деле нет массивов, если присмотреться, просто что-то вроде этого. Фортран имеет настоящие массивы. Что облегчает компиляцию для определенных типов алгоритмов, особенно для параллельных машин.

Глубоко в таких вещах, как система времени выполнения и соглашения о вызовах, C и современный Fortran достаточно похожи, так что трудно понять, что изменит ситуацию. Обратите внимание, что C здесь действительно является базовым C: C ++ - это совершенно другая проблема с очень разными характеристиками производительности.

23 голосов
/ 30 октября 2008

Нет такой вещи, чтобы один язык был быстрее другого, поэтому правильный ответ - нет .

Что вам действительно нужно спросить, так это «компилируется ли код компилятором Fortran X быстрее, чем эквивалентный код, компилируемый компилятором C Y?» Ответ на этот вопрос, конечно, зависит от того, какие два компилятора вы выберете.

Другой вопрос, который можно было бы задать, звучал бы так: «Учитывая тот же объем усилий, приложенных для оптимизации их компиляторов, какой компилятор будет производить более быстрый код?» Ответ на этот вопрос на самом деле будет Фортран . Компиляторы Fortran имеют ряд преимуществ:

  • Fortran пришлось конкурировать с Assembly в тот день, когда некоторые пообещали никогда не использовать компиляторы, поэтому он был разработан для скорости. C был разработан, чтобы быть гибким.
  • Ниша Фортрана была хрустом номера. В этом домене код никогда никогда не будет достаточно быстрым. Поэтому всегда было большое давление, чтобы язык был эффективным.
  • Большая часть исследований по оптимизации компилятора проводится людьми, заинтересованными в ускорении обработки кода на языке Fortran, поэтому оптимизация кода на Fortran является гораздо более известной проблемой, чем оптимизация любого другого скомпилированного языка, и сначала в компиляторах Fortran появляются новые инновации.
  • Biggie : C поощряет гораздо большее использование указателей, чем Fortran. Это резко увеличивает потенциальную область действия любого элемента данных в программе на C, что значительно затрудняет их оптимизацию. Обратите внимание, что Ada также лучше, чем C в этой области, и является гораздо более современным языком OO, чем обычно встречающийся Fortran77. Если вам нужен OO-язык, который может генерировать более быстрый код, чем C, это вариант для вас.
  • Опять же из-за своей узкой ниши заказчики компиляторов Fortran, как правило, больше заботятся об оптимизации, чем заказчики компиляторов C.

Однако ничто не мешает кому-то приложить массу усилий для оптимизации своего компилятора C и заставить его генерировать лучший код, чем компилятор Fortran их платформы. Фактически, большие продажи, генерируемые компиляторами C, делают этот сценарий вполне осуществимым

22 голосов
/ 30 октября 2008

Есть еще один предмет, где Фортран отличается от С - и, возможно, быстрее. У Fortran есть лучшие правила оптимизации, чем у C. В Fortran порядок вычисления выражений не определен, что позволяет компилятору оптимизировать его - если кто-то хочет форсировать определенный порядок, нужно использовать круглые скобки. В C порядок намного строже, но с опциями «-fast» они более смягчены и «(...)» также игнорируются. Я думаю, что у Фортрана есть путь, который приятно лежит посередине. (Ну, IEEE усложняет работу, поскольку некоторые изменения порядка оценки требуют, чтобы не происходило переполнения, что либо должно игнорироваться, либо затрудняет оценку).

Другая область более разумных правил - комплексные числа. Мало того, что до C 99 у них были они, также правила управляют ими лучше в Фортране; поскольку библиотека gfortran на Фортране частично написана на С, но реализует семантику на Фортране, GCC получила опцию (которую также можно использовать с «обычными» программами на С):

-fcx-Fortran-правила Комплексное умножение и деление следуют правилам Фортрана. Уменьшение диапазона выполняется как часть сложного деления, но нет проверки, является ли результат сложного умножения или деления «NaN + I * NaN», с попыткой спасти ситуацию в этом случае.

Упомянутые выше правила псевдонимов являются еще одним бонусом, а также - по крайней мере в принципе - операциями с целым массивом, которые при правильном учете оптимизатором компилятора могут привести к более быстрому коду. С другой стороны, некоторые операции занимают больше времени, например если кто-либо выполняет присваивание выделяемому массиву, необходимо выполнить много проверок (перераспределить? [функция Fortran 2003], имеет шаги с массивами и т. д.), которые делают простую операцию более сложной за кулисами - и, следовательно, медленнее, но делает язык более мощным. С другой стороны, операции с массивами с гибкими границами и шагами облегчают написание кода - и компилятор обычно лучше оптимизирует код, чем пользователь.

В целом, я думаю, что и C, и Fortran примерно одинаково быстры; выбор должен быть больше: какой язык больше нравится, или более полезны операции с целым массивом Fortran и его лучшая переносимость, или лучшее взаимодействие с системными библиотеками и библиотеками графического интерфейса пользователя в C.

14 голосов
/ 28 сентября 2008

В языках Fortran и C ничего нет, что делает один быстрее другого для определенных целей. Существуют вещи о конкретных компиляторах для каждого из этих языков, которые делают некоторые благоприятными для определенных задач больше, чем другие.

В течение многих лет существовали компиляторы Fortran, которые могли творить чёрную магию с вашими числовыми процедурами, делая безумно быстрыми многие важные вычисления. Современные компиляторы Си не могли этого сделать. В результате в Фортране выросло множество великолепных библиотек кода. Если вы хотите использовать эти хорошо протестированные, зрелые, замечательные библиотеки, вам нужен компилятор Fortran.

Мои неофициальные наблюдения показывают, что в наши дни люди кодируют свои тяжелые вычислительные ресурсы на любом старом языке, и если это занимает некоторое время, они находят время на каком-нибудь дешевом вычислительном кластере. Закон Мура делает нас всех дураками.

13 голосов
/ 30 октября 2008

Я сравниваю скорость Fortran, C и C ++ с классическим тестом Levine-Callahan-Dongarra от netlib. Многоязычная версия с OpenMP http://sites.google.com/site/tprincesite/levine-callahan-dongarra-vectors C более уродлив, поскольку начался с автоматического перевода, а также вставил restrict и pragmas для определенных компиляторов. C ++ - это просто C с шаблонами STL, где это применимо. На мой взгляд, STL - это смешанный пакет с точки зрения того, улучшает ли он ремонтопригодность.

Существует только минимальное применение автоматического встраивания функции, чтобы увидеть, в какой степени это улучшает оптимизацию, поскольку примеры основаны на традиционной практике Фортрана, где мало места встраиванию.

Компилятору C / C ++, который на данный момент наиболее широко используется, не хватает автоматической векторизации, на которую в значительной степени опираются эти тесты.

В связи с постом, который был опубликован непосредственно перед этим: есть несколько примеров, где в Фортране используются скобки для указания более быстрого или более точного порядка оценки. Известные компиляторы C не имеют возможности соблюдать скобки, не отключая более важные оптимизации.

...