Советы и рекомендации по повышению производительности кода Fortran [закрыто]

в рамках моих докторских исследований я работаю над разработкой численных моделей циркуляции атмосферы и океана. Они включают в себя численное решение систем PDE порядка ~10^6 точек сетки, более ~10^4 временных шагов. Таким образом, типичное моделирование модели занимает от нескольких часов до нескольких дней при запуске в MPI на десятках процессоров. Естественно, важно максимально повысить эффективность модели, убедившись, что результаты идентичны по байтам.

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

какие другие факторы представления чувствительные там? На данный момент мне интересно несколько:

1) имеет ли значение порядок математических операций дело? Например, если у меня есть:

a=1E-7 ; b=2E4 ; c=3E13
d=a*b*c

будет ли D оценивать с разной эффективностью на основе порядка умножения? В настоящее время это должно быть специфичным для компилятора, но есть ли прямой ответ? Я замечаю, что d получает (немного) другое значение на основе порядка (предел точности), но повлияет ли это на эффективность или нет?

2) Передача лотов (например, десятков) массивов в качестве аргументов подпрограмме против доступа к этим массивам из модуля в подпрограмме?

3) конструкции Fortran 95 (FORALL и где) против DO и IF? Я знаю, что это имело значение еще в 90-х годах, когда векторизация кода была большой вещью, но есть ли какая-то разница с современными компиляторами, способными векторизовать явные циклы DO? (Я использую компиляторы PGI, Intel и IBM в своей работе)

4) Повышение числа до целой степени по сравнению с умножением? Например:

b=a**4

или

b=a*a*a*a

меня учили всегда использовать последнее, где это возможно. Влияет ли это на эффективность и/или точность? (вероятно, также зависит от компилятора)

пожалуйста, обсудите и / или добавьте любые трюки и советы, которые вы знаете о повышении эффективности кода Fortran. Что там еще? Если вы знаете что-то конкретное о том, что каждый из компиляторов выше, связан с этим вопрос, пожалуйста, включите и это.

добавлено: обратите внимание, что у меня нет никаких узких мест или проблем с производительностью как таковых. Я спрашиваю, есть ли какие-либо общие правила для оптимизации кода в смысле операций.

спасибо!

3 ответов


у вас есть априорные идеи о том, что делать, и некоторые из них могут действительно помочь, но самый большой выигрыш в апостериорной anaylsis.
(добавлено: другими словами, становится a*b*c в другом порядке может сэкономить пару циклов (в чем я сомневаюсь), но в то же время вы не знаете, что вы не получаете огорошен тем, что потратив 1000 циклов без уважительной причины.)

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

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

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

вот примеры вещей, которые вы можете найти:

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

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


Извините, но все трюки, которые вы упомянули просто ... нелепый. Точнее, они не имеют смысла на практике. Например:

  • что может быть преимуществом использования половины(=0.5), а не 0.5?
  • idem для вычислений a**4 или a*a*a*a. (a*a)** 2 будет еще одна возможность. Мой личный вкус-это**4, потому что хороший компилятор, который автоматически выбирает лучший способ.

на **, единственный момент, который может иметь значение разница между a ** 4 и a ** 4., последний является гораздо более трудоемким процессором. Но даже эта точка не имеет смысла без измерения в реальной симуляции.

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

если часть показывает высокий процент CPU, например, 50%, не забывайте это оптимизация только этой части не может разделить стоимость общего кода в два раза больше. В любом случае, начните оптимизационную работу с самой дорогой части (горлышко бутылки).

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


Я поддерживаю совет, что эти трюки, которым вас учили, глупы в эту эпоху. Компиляторы делают это за вас сейчас; такие микро-оптимизации вряд ли будут иметь существенное значение и могут не быть переносимыми. Напишите понятный и понятный код. Тщательно выберите свой алгоритм. Одна вещь, которая может иметь значение,-это использование индексов многомерных массивов в правильном порядке ... преобразование массива M X N в N X M может помочь в зависимости от шаблона доступа к данным программа. После этого, если ваша программа слишком медленная, измерьте, где потребляется процессор и улучшите только эти части. Опыт показывает, что угадывание часто неправильно и приводит к написанию более непрозрачного кода ни по какой причине. Если вы сделаете раздел кода, в котором ваша программа тратит 1% своего времени в два раза быстрее, это не имеет никакого значения.

вот предыдущие ответы на FORALL и где:как я могу гарантировать, что моя конструкция Fortran FORALL распараллеливается? и делают ли конструкции Fortran 95, такие как WHERE, FORALL и SPREAD, как правило, приводят к более быстрому параллельному коду?