пятница, 27 августа 2010 г.

FORTRAN: «продвинутые» возможности, высокопроизводительные вычисления

Какое-то время я отложил ведение блога... будем считать это летними каникулами! Сейчас опять появилось время/желание порассказывать о чём-нибудь интересном.

Одним из первых событий, которое про которое хотелось бы написать - выход продолжения моей статьи Fortran в Linux: вчера, сегодня, завтра!. В 63-м номере журнала "Open Source" была опубликована моя статья "FORTRAN: «продвинутые» возможности, высокопроизводительные вычисления", текст который можно прочитать и здесь:


Сегодня мы расскажем о «продвинутых» возможностях Фортрана: о многопоточных вычислениях, о возможности подключения C/С++ процедур при разработке приложений и о модной последнее время теме: о создании высокопроизводительных приложений, работающих на графических процессорах (технология CUDA).

OMG? Нет — OMP!

Итак, что такое OMP? Это аббревиатура от Open Multi-Processing — набор директив компилятора, библиотечных процедур и переменных окружения, которые предназначены для программирования многопоточных приложений на многопроцессорных системах с единой памятью на языках C, C++ и Fortran.

Разработку спецификации OpenMP ведут несколько крупных производителей вычислительной техники и программного обеспечения, чья работа регулируется некоммерческой организацией, называемой OpenMP Architecture Review Board (ARB). Эта организация публикует стандарты работы OpenMP — API. Первый стандарт API 1.0 для Фортрана был опубликован в 1997 году (для языка С — в 1998). В 2000 году вышел API 2.0 для Фортрана (для С — в 2002) . Версия 2.5 (вышла в 2005 году) объединяет спецификации для C/C++ и Fortran. Текущая версия API имеет номер 3.0 и опубликована в 2008 году.

В следующей таблице представлен список компиляторов, поддерживающих технологию OpenMP:

Производитель
Компилятор/Информация
GNU
Начиная с версии 4.3
http://gcc.gnu.org/projects/gomp/
Версия OpenMP API — 3.0
Пример: gfortran hello.f -o hello.exe -fopenmp
IBM
XL Fortran V10.1
www-01.ibm.com/software/awdtools/fortran/
Версия OpenMP API — 2.5
xlf90_r -qsmp=omp -o exename filename.f
Oracle

Sun Studio C/C++/Fortran

http://docs.sun.com/app/docs/doc/820-7883
Версия OpenMP API — 3.0
-xopenmp опция компиляции
Intel
C/C++ / Fortran Intel Compiler
http://software.intel.com/en-us/articles/getting-started-with-openmp/
Версия OpenMP API — 3.0
-Qopenmp в Windows, -openmp в Linux или Mac OSX
C/C++ / Fortran
http://www.pgroup.com/resources/openmp.htm
Версия OpenMP API — 3.0
compile with -mp
Absoft Pro Fortran Compiler
параметр: -openmp
C/C++ / Fortran
C/C++ / Fortran
-mp опция компиляции
HP
C/C++ / Fortran
+Oopenmp опция компиляции


Как видно, практически все современные компиляторы поддерживают эту технологию. Основной сайт, посвящённый OpenMP.

В OpenMP используется модель параллельного выполнения "ветвление-слияние". Программа начинается как единственный поток выполнения (называемый начальным потоком). Когда он встречает параллельную конструкцию, создаётся новая группа потоков, состоящая из главного и некоторого числа дополнительных потоков. Все члены новой группы (включая главный) выполняют код внутри параллельной конструкции. После параллельной конструкции выполнение пользовательского кода продолжает только главный поток. В параллельный регион могут быть вложены другие параллельные регионы, в которых каждый поток первоначального региона становится основным для своей группы потоков. Вложенные регионы могут в свою очередь включать регионы более глубокого уровня вложенности.

В качестве простейшего примера можно рассмотреть следующую программу (fortran free-form, взято из Википедии):

  1.  
  2. program hello90
  3.     use omp_lib
  4.     integer:: id, nthreads
  5.  
  6.     !$omp parallel
  7.     private(id) id = omp_get_thread_num()
  8.     write (*,*) 'Hello World from thread', id
  9.     !$omp barrier
  10.     if ( id == 0 ) then
  11.         nthreads = omp_get_num_threads()
  12.         write (*,*) 'There are', nthreads, 'threads'
  13.     end if
  14.     !$omp end parallel
  15. end program
  16.  

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

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

C/C++ и Fortran — братья на век!

Иногда при разработке сложных программ возникает необходимость использовать/создавать процедуры или функции, написанные на других языках. Такой подход называется «смешанное программирование» (Mixed Language Programming). Нас интересует возможность использовать функций, написанных на С/С++ в Фортране и наоборот. Такая возможность существует, однако при этом важно учитывать соглашения об именах, принятые в этих языках.

По умолчанию компилятор фортрана преобразует буквы в именах подпрограмм в верхний регистр. Компилятор С такое преобразование не выполняет, следовательно, подпрограмме, написанной на С и вызываемой из программы на фортране, следует присвоить имя с учётом правильного регистра: CALL ABPROC (I, X)
Соответствующая данному вызову подпрограмма С должна содержать буквы в верхнем регистре.

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

FORTRAN: call subra( i, x)
C: subra_( int *i, float *x)

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

CUDA — вычисления на графических процессорах

CUDA (англ. Compute Unified Device Architecture) — технология, позволяющая программистам реализовывать алгоритмы, выполнимые на графических процессорах ускорителей GeForce восьмого поколения и старше (GeForce 8 Series, GeForce 9 Series, GeForce 200 Series), Nvidia Quadro и Tesla компании Nvidia.

Первоначально технология CUDA позволяла включать в текст программ специальные функции (написанные на особом диалекте С), которые выполнялись на графическом процессоре. Сейчас программирование для CUDA доступно в том числе для следующих языков: Python, Java, .NET, MATLAB и Fortran.

Вот здесь, например, можно найти библиотеку, которая позволяет в интегрировать приложения Фортрана функции, выполняемые на графических процессорах. Данная библиотека является бесплатной и доступна как для Windows так и для Linux операционных систем. В среде Linux заявлена поддержка g77/gfortran компиляторов, а так же компилятора от фирмы Intel — ifort. В Windows данная библиотека может быть использована с Intel Visual Фортраном.

Другим компилятором, в котором реализована данная технология, является компилятор от фирмы Portland Group: PGI CUDA Fortran Compiler. Данный компилятор является коммерческим, а разработан он совместно с компанией Nvidia.

Стоит также упомянуть о библиотеке flagon, которая также предоставляет возможность использовать технологию CUDA при работе с Фортраном. Данная библиотека разрабатывалась как коммерческий продукт компанией «Fantalgo, LLC», однако позже была выложена под открытой лицензией LGPL.

2 комментария:

Анонимный комментирует...

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

Анонимный комментирует...

Антон, может, не по теме вопрос. Но всё же спрошу.
Как мне компилировать с помощью gfortran (с использованием cygwin), чтобы полученный exe-файл не требовал никаких библиотек (типа libgfortran-3.dll) при вызове? Чтобы просто запускался exe-шник.
Заранее благодарю!