Pull to refresh

К 70-летию Фортрана. Историческая справка. Часть II

Level of difficultyEasy
Reading time10 min
Views3.8K

Я не знаю, на что будет похож язык 2000 года, но знаю, что он будет называться Фортран (Т. Хоар, 1982).

Первую часть статьи, рассказывающую об истории классического Фортрана (1953-1990), можно прочитать здесь.

Как отмечалось в первой части, условно эволюцию языка Фортран можно разделить на классический период (Фортран I – Фортран IV), когда ведущую роль в разработке занимала фирма IBM, язык абсолютно доминировал среди программистов (особенно в США) и сохранял значительную преемственность с самой первой версией; и современный период (Фортран 90 – Фортран 2018), когда разработка велась в основном ISO, синтаксис и семантика языка были значительно осовременены, но, несмотря на это, язык был уже вытеснен на периферию инструментальных средств. Версия Фортран 77 занимает промежуточное положение между этими периодами.

Фортран 90

С одной стороны, накапливалось несоответствие архаичных особенностей классического Фортрана существующим практикам программирования, а с другой – понемногу начали уходить на покой аксакалы, привыкшие к классическому Фортрану пятидесятых-шестидесятых годов, и приходить новые люди. В итоге 14-летних размышлений над судьбами программирования, ISO в 1991 году выпустил стандарт Фортран 90, радикальным образом поменявший синтаксис и семантику языка Фортран. Одно только согласование этого стандарта заняло 6 лет (первоначально он задумывался как Фортран 85).

В целом, сущность изменений сводилась к позиционированию современного Фортрана как языка параллельных и конвейерных вычислений. Стандарт вобрал в себя как многие свойства языка PL/I, так и дальнейшее развитие операций с массивами, которые впервые были реализованы в качестве расширений языка для векторно-конвейерных суперкомпьютеров, таких как Cray. (Как верно указал в комментариях@MiIs,многое унаследовано также от языка Ада, например, большое влияние Ады видно в модульной структуре).

Фактически, современный Фортран (начиная с Фортрана 90) отличается от классического Фортрана настолько же, насколько современный C++ отличается от C, если не больше.

Основные нововведения Фортрана 90:

  • Формат написания кода стал свободным, упразднено деление строки на позиции. В конструкциях языка стало возможно использовать строчные буквы, и в честь этого даже название языка официально изменено с FORTRAN на Fortran. Комментарии стало возможно размещать в тех же строках, что и операторы.

  • Количество значащих символов в идентификаторах увеличено с 6 до 31.

  • Массивы теперь рассматриваются, как объекты первого класса. Арифметические операции и встроенные функции теперь могут принимать в качестве аргументов массивы. Возможно записывать литеральные константы и выражения, имеющие тип массива. Из массивов можно выделять сечения – подмассивы, которые также рассматриваются, как массивы, в том числе фильтруя элементы по логическим маскам. Введён оператор WHERE для селективного присваивания элементов массивов. Всё это – самое главное изменение; Фортран теперь стал позиционироваться, как язык работы с массивами, как ранее APL, и приобрёл богатый набор средств поддержки конвейерных вычислений.

  • Появились единицы совместной компиляции – модули. Интерфейс модуля проверяется при компиляции использующего его кода.

  • Появились рекурсивные процедуры и функции, динамическое размещение переменных в памяти (в стеке и в куче), указатели.

  • Появилась спецификация входных и выходных формальных параметров.

  • Расширен синтаксис описания типов, позволяющий указывать множество атрибутов типа объекта.

  • Появились структурные типы данных и элементы объектно-ориентированного программирования.

  • Приняты расширения из военного стандарта, в том числе операторные скобки DO ... END DO, оператор DO WHILE, операторы CYCLE и EXIT, оператор IMPLICIT NONE. Стало считаться хорошим тоном автоматически начинать любой модуль с IMPLICIT NONE.

  • Появился оператор выбора SELECT CASE.

  • Множество более мелких изменений.

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

Очень забавная история произошла в Фортране 90 с конструкторами массивов. В синтаксис языка необходимо было ввести специальные скобки для конструктора. Сейчас конструктор записывается, например, так: [ (x**i, i=0,N) ] – массив, содержащий полином N-й степени от x. Здесь квадратными скобками обозначено массивное выражение, а круглыми – неявный цикл, представляющий собой генератор его элементов. Но нельзя ж было за какие-то 38 лет просто так взять и ввести в алфавит языка квадратные скобки, которые отсутствовали на перфораторе IBM 704 и даже на некоторых ранних устройствах S/360! Поэтому было принято компромиссное решение кодировать их диграфами (/ и /), то есть, в нашем случае, (/(x**i, i=0,N)/). Учитывая, что косые черты сами по себе могли иногда выступать в Фортране в качестве специфических скобок (например, в описании общего блока памяти), такая конструкция невероятно запутывала программистов, так как казалось, что тут три пары скобок, а не две.

К интересным особенностям современного Фортрана относится то, что он позволяет описывать массивы, количество измерений в которых заранее неизвестно (дальнейшая универсализация определения массива ожидается в стандарте 2023 года, который обсуждается ниже).

Фортран 95

Дальше дело пошло проще. Всего через 6 лет, в 1997 году, был выпущен стандарт Фортран 95.

  • Введены дополнительные конструкции для векторных вычислений с массивами, такие как оператор FORALL и вложенные WHERE.

  • Введён атрибут пользовательских функций ELEMENTAL, позволяющий им, подобно встроенным функциям, работать как со скалярными элементами, так и с массивами.

  • Введены атрибуты PURE и IMPURE, специфицирующие наличие побочного эффекта у функции.

  • На 45 году разработки языка было решено ввести в алфавит квадратные скобки. Конструкторы приобрели человеческий вид.

  • Из Фортрана исключены циклы с управляющей переменной вещественного типа (хотя в большинстве реализаций компиляторов они остались).

Пример программы:

program poly

  implicit none
  integer, parameter :: n = 10
  real :: A(0:n), X(0:n), x0, p 
  integer :: i

  read *, (A(i), i=n,0,-1), x0

  X = [ (x0**i, i=0,n) ] 
  p = dot_product (A, X)

  print *, p

end program

Фортран 2003

Стандарт Фортран 2003 принят в 2004 году, в нём, наконец, был стандартизован асинхронный ввод-вывод. Набор атрибутов расширен для описания взаимодействия с программами на языке Си. Расширены средства динамического распределения памяти и поддержки ООП, которые всё равно в Фортране никто не использует.

В тот же период независимыми разработчиками был разработан и реализован интерфейс OpenMP для Фортрана и позже для C/C++, позволяющий управлять исполнением кода на параллельных и конвейерных архитектурах. Например:

!$omp parallel do
do i = 1, 10000
  a(i) = 2.*i
end do

Выполнение этого цикла будет автоматически разделено на части по числу процессорных ядер в системе, и эти части выполнятся параллельно (например, по 2500 элементов на 4 ядрах).

Фортран 2008

Очень важный стандарт, принятый в 2010 году и до сих пор эффективно реализованный не во всех компиляторах, хотя и формально совместимых с ним.

  • Поддержка вычислительной модели Coarray Fortran для массивно-параллельных архитектур, которая изначально была разработана как отдельный фортраноподобный язык F--. Программа в Coarray Fortran параллельно запускается на массиве вычислительных узлов, и каждый экземпляр может работать либо со своими локальными переменными, либо с переменными другого узла. Так, если у нас есть переменная integer :: i, то просто i будет означать значение на своём узле, а i[N] – значение на узле N (а и правда, не вводить же в язык какие-нибудь фигурные скобки для межпроцессной коммуникации, после того, как всего 13 лет назад уже придумали квадратные для конструкторов массивов).

  • Оператор параллельного цикла DO CONCURRENT. Например, заголовок цикла do concurrent (i=1:100, j=1:200) означает, что 20000 итераций могут независимо параллельно исполняться вычислительными ядрами в любых разбиениях. Теоретически это даёт то же самое, что и явное указание параллелизма в OpenMP, если компилятор поддерживает такое распараллеливание.

  • Атрибут ASYNCHRONOUS для асинхронных переменных в MPP средах.

  • Операторные скобки BLOCK ... END BLOCK, позволяющие локализовать переменные более узко, чем тело подпрограммы или функции (ещё одно заимствование из PL/I, имеющее, однако, дополнительную важность для гранулирования доступа к асинхронным объектам).

  • Атрибут CONTIGUOUS для более эффективного управления памятью.

К этому моменту язык Фортран достиг уже внушающих уважение размеров. Описание языка IBM XL Fortran for AIX, которое автор полагает лучшим доступным изложением Фортрана 2008, занимает 1106 страниц мелким шрифтом (для сравнения, такое же описание C/C++ от IBM занимает 562 страницы).

Фортран 2018

Для разнообразия, стандарт Фортран 2018 действительно был принят в 2018 году. Он включает расширение возможностей по взаимодействию с языком Си и расширяет язык в части управления массивно-параллельными вычислениями.

  • Введён ряд операторов (FORM TEAM, CHANGE TEAM, SYNC TEAM, FAIL IMAGE) и большое количество встроенных функций для объединения вычислительных узлов в “команды” для выполнения различных подзадач. Если в классической модели coarray образца 2008 года все узлы выполняют один и тот же код с разными данными, то в модели 2018 года узлы могут группироваться в команды для выполнения различных блоков кода разными командами.

  • Введено понятие коллективности подпрограмм, которое по сути представляет собой реентерабельность внутри команды.

Пример программы:

! Вектор a длиной N*P распределён среди P узлов.
! Каждый узел для представления своей части
! вектора a использует массив A(0:N+1),
! содержащий относящиеся к узлу элементы и
! значения гало для обмена с соседями справа и
! слева. Узлы делятся на две команды, которые
! работают независимо, но периодически
! обмениваются гало. Перед обменом все узлы
! инициирующей обмен команды должны быть
! синхронизированы, и для обмена требуются
! коиндексы инициирующей команды.

USE, INTRINSIC :: ISO_FORTRAN_ENV, ONLY: TEAM_TYPE 
TYPE(TEAM_TYPE) :: INITIAL, BLOCK
REAL :: A(0:N+1)[*]
INTEGER :: ME, P2
INITIAL = GET_TEAM()
ME = THIS_IMAGE()
P2 = NUM_IMAGES()/2
FORM TEAM(1+(ME-1)/P2,BLOCK) 
CHANGE TEAM(BLOCK,B[*]=>A)
  DO
    ! Вычисляем что-нибудь в команде
    ! ...
    ! Меняемся значениями гало с соседней командой
    SYNC TEAM(INITIAL)
    IF(ME==P2  ) B(N+1) = A(1)[INITIAL::ME+1] 
    IF(ME==P2+1) B(0)   = A(N)[INITIAL::ME-1] 
    SYNC TEAM(INITIAL)
   END DO
END TEAM

Из этой программы (скопированной непосредственно из документа ISO) видно, что современный Фортран получил практически все те особенности, за которые увлечённые программированием люди любили PL/I: он имеет огромное описание, многочисленные загадочные атрибуты объектов, позволяет использовать ключевые слова в качестве имён переменных и содержит много возможностей, специально предназначенных для таких случаев, которые обычный программист не встретит ни разу за всю свою жизнь.

Бонус: Будущий Фортран 2023

В 2023 году ожидается принятие нового стандарта, условно – Фортран 2023. Его основные ожидаемые нововведения:

  • Конструкция NOTIFY для синхронизации узлов через высокоскоростную сеть.

  • Атрибут SIMPLE для подпрограмм и функций, которые не только не имеют побочных эффектов (PURE), но и ссылаются на нелокальные переменные только через свои параметры. Это важно для оптимизации параллельных вычислений, так как такой код можно вызывать асинхронно в разных параллельных потоках.

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

  • Введён оператор @, по сути, для замыкания индексации массивов, когда вместо индексов массива выступает другой массив. Например, A(@[1,3]) – то же самое, что A(1,3). Естественно, можно написать A(@V). Также можно описывать массивы, размерность которых задаётся другими массивами. Очевидное заимствование оператора □ языка APL.

  • Оператор DO CONCURRENT может включать спецификацию редукции, например:

    do concurrent (i = 1, n) reduce(+:a) reduce(max:b)
      a = a + x(i)**2
      b = max(b,x(i))
    end do

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

  • Синтаксический сахар: условные выражения, перечисления, больше полезных встроенных функций.

Ещё бонус: Как припасть к источнику благодати

Как понятно из вышеописанного, на сегодняшний день Фортран преимущественно является инструментом для программирования суперкомпьютеров с массивно-параллельной и, в меньшей степени, векторно-конвейерной моделью обработки. На таких машинах используются специализированные коммерческие компиляторы, такие как IBM XL Fortran, Cray Fortran и тому подобные. В то же время, есть что запустить и в домашних условиях.

Стандартом де-факто для обучения программированию на Фортране и некоммерческого использования является компилятор GNU Fortran (gfortran). Этот компилятор имеет общий кодогенератор с gcc, реализован на огромном количестве платформ (в том числе Linux, macOS, Windows). GNU Fortran полностью поддерживает стандарты Фортран 95 и Фортран 90. Ещё он поддерживает значительную часть стандартов Фортран 2003 и Фортран 2008, а также кусочек стандарта Фортран 2018 (в части взаимодействия с Си). GNU Fortran компилирует некоторые циклы DO CONCURRENT, но, к большому сожалению, генерирует по ним последовательный код. Этот компилятор может эффективно распараллеливать код только при использовании конструкций OpenMP. В архитектуре x86_64 поддерживается конвейеризация в объёме векторных инструкций процессоров Intel и AMD (или вручную на GPU через OpenACC).

Перспективным свободно распространяемым компилятором является flang, реализованный на базе llvm. Особенностью flang является кодогенератор, унаследованный от коммерческого компилятора фирмы NVIDIA, позволяющий автоматически компилировать код для использования конвейерных вычислений на графических акселераторах NVIDIA. Однако, flang пока не достиг стадии окончательно оформленного дистрибутива, предлагается только его сборка из актуальных исходных текстов, которая может представлять проблему в ряде окружений.

Сам вышеупомянутый коммерческий компилятор NVIDIA HPC Fortran (он же CUDA Fortran) позволяет вручную и автоматически распараллеливать и векторизовать код программ (в том числе циклы do concurrent) как на ядра SMP, так и на графические акселераторы NVIDIA.

Для процессоров Intel популярным компилятором является Intel Fortran, существующий в двух версиях – более старый Intel Fortran Compiler Classic (ifort) и более новый, находящийся в процессе разработки, Intel Fortran (ifx) на базе llvm. Компилятор ifx реализует не все возможности ifort. К достоинствам ifort относится способность компилировать программы на Фортране 66 и Фортране 77 (хотя и не проверять соответствие текстов программ этим стандартам), а также мощный оптимизатор, в том числе – автоматический распараллеливатель последовательных программ. К недостаткам относится отсутствие поддержки многобайтовой кодировки символов UCS-4, что затрудняет обработку не-ASCII символов в текстовых строках.

Оксфордская компания NAG, известная своей библиотекой программ для научных расчётов, продаёт свой собственный компилятор NAG Fortran. Компилятор nagfor отличается очень тщательной проверкой текста программы на фактические отступления от стандарта и потенциальные ошибки, но в смысле эффективности кода значительно уступает свободному gfortran (по крайней мере, на платформе Intel). Автору не удалось ни на одном тесте быстродействия кода получить превосходство nagfor над gfortran, при этом на некоторых тестах nagfor проигрывал в несколько раз.

Разработка на Фортране поддерживается, например, в свободно распространяемой IDE Eclipse. В штатном дистрибутиве предлагается вариант настройки для научных вычислений, который включает поддержку компиляторов GNU Fortran, Intel Fortran, IBM Fortran XL. Доступна локальная и удалённая отладка. Использование Eclipse с Фортраном возможно в Linux, Windows и macOS (к сожалению, в последних версиях macOS сломана совместимость с отладчиком gdb, поддерживающим Фортран; с другой стороны, не станет же фортрановский программист расстраиваться из-за сломанного отладчика?)

Only registered users can participate in poll. Log in, please.
На каких версиях Фортрана вам доводилось писать код?
0% Фортран I0
0% Фортран II0
0% Фортран III0
36.84% Фортран IV (Фортран 66)35
31.58% Фортран 7730
18.95% Фортран 9018
14.74% Фортран 9514
9.47% Фортран 20039
5.26% Фортран 20085
4.21% Фортран 20184
0% Фортран 20230
25.26% Как вы могли такое обо мне подумать?24
5.26% Не помню5
4.21% Что такое Фортран?4
95 users voted. 20 users abstained.
Tags:
Hubs:
Total votes 10: ↑10 and ↓0+10
Comments13

Articles