Компиляция и запуск

Запуск задач на кластере в системе SLURM

При запуске задачи пользователя на счет
- необходимо учитывать ограничения по ресурсам на вычислителях для пользователей (и не забывать о них);
- желательно использовать тот модуль установки переменных окружения, с которым программа была откомпилирована;
- пока задача не просчиталась, нельзя ее перекомпилировать, удалять исполняемый файл и менять входные данные.

Запуск программ осуществляется в системе SLURM. В результате запуска задача помещается в очередь заданий и ей присваивается уникальный идентификатор (его можно узнать командами mqinfo, mps или squeue, sacct). По умолчанию задаче пользователя выделяется по 1 ГБ оперативной памяти на каждое вычислительное ядро (при необходимости размер исполняемой программы в байтах можно узнать с помощью команды size).

Данная инструкция описывает общие и относящиеся к MPI-программам команды SLURM.
Особенности запуска параллельных OpenMP-, MATLAB-, ANSYS-программ рассматриваются в отдельных инструкциях:
    О запуске приложений с OpenMP, PGI Accelerator и OpenACC
    Использование системы Matlab для параллельных вычислений (подробно в Параллельный Matlab)
    Запуск программ из пакета ANSYS

Команды SLURM начинаются с буквы s.
На основе этих команд для удобства пользователей (в частности, обеспечения преемственности при переходе на SLURM, см. [6]) были реализованы упрощённые команды запуска MPI-, MATLAB-, ANSYS-программ и информационные команды (начинающиеся, за одним исключением, с буквы m).
Упрощённые команды и основные команды SLURM приведены ниже; подробнее о SLURM см., например, в [1-5]; полная информация выдаётся с помощью команды man.


Упрощённые команды

mqrun, замена mpirun, — запуск MPI-программы, аналог команды sbatch
mlrun, mlprun, mlgrun — запуск MATLAB-программ; matlab — запуск MATLAB
ansysrun — запуск ansysV, cfx5solve и fluent-программ, где V- номер текущей версии
mqinfo — выдача информации об узлах и очереди заданий с помощью команд sinfo и squeue:
                1) разновидность команды sinfo выдаёт информацию об узлах (см. Пример выдачи sinfo),
                в частности, о числе процессоров и ядер на узле в зависимости от типа узла (от раздела),
                об общем числе свободных ядер и др.;
                2) команда squeue выдаёт информацию об очереди заданий.
mps — выдача информации об узлах и задачах только самого пользователя, действует как команда
                mqinfo -u $USER -l
mqdel,  mkill — отмена выполнения задачи (ожидающей старта или уже стартовавшей),
                действуют как команда scancel

Команда mqrun (замена mpirun, аналог sbatch ) c параметрами –np и –maxtime (допустимы –n и –t для sbatch), задающими соответственно число процессов и время предполагаемого счета в минутах, запускает в пакетном режиме успешно откомпилированную С- или Fortran-программу, например
    mqrun -np 8 -maxtime 20 mytest

(вместо     mpirun –np 8 –maxtime 20 mytest )
где для mytest затребовано формирование 8 процессов, а время счета ограничено 20-ю минутами.
В ответ в строке вида
    Submitted batch job 1475

выдаётся уникальный идентификатор задачи в очереди заданий, здесь 1475.
Уникальный идентификатор используется в командах отмены выполнения задания, например
    mqdel 1475
    (или    mkill 1475)
Внимание!
1. Для запущенной таким образом задачи сохранена запись выходного файла в каталог вида имя_программы.номер. Номера возрастают, начиная с 1 (например, mytest.1).
Пользователь должен сам удалять ненужные каталоги.
2. Для увеличения оперативной памяти можно воспользоваться опцией -m <MB>, где MB - память в мегабайтах (например, -m 4000).
3. В команде mqrun доступны основные опции старой команды mpirun (в частности -stdin, -stdout, -stderr); смотрите
    mqrun -help


Основные команды SLURM

Команды запуска задач

Система SLURM позволяет с помощью команд srun и sbatch работать соответственно в интерактивном и пакетном режимах.
Пакетный режим является основным в работе с кластером.

Команда srun для запуска интерактивной программы имеет вид
    srun -n <число процессов> -t <время> <имя программы> [<параметры программы>] [&]


Команда sbatch для запуска программы в пакетном режиме имеет вид
    sbatch -n <число процессов> -t <время> <имя скрипта>

или
    sbatch -n <число процессов> -t <время> --wrap="srun <имя программы> [<параметры программы>]"


Внимание!
Библиотека OpenMPI работает только с командой sbatch и при этом перед именем программы вместо srun добавляется orterun:
    sbatch -n <число процессов> -t <время> --wrap="orterun <имя программы> [<параметры программы>]"


Параметры:
-n — задаёт число процессов (tasks); если не задано, то по умолчанию n=1;
-t — заказывает время для решения задачи; при отсутствии t выделяется 30 минут (по умолчанию);
20 часов - максимальное время, выделяемое для счета задачи в будние дни (с 9 часов понедельника до 16 часов пятницы);
85 часов - максимальное время, выделяемое для счета задачи на выходные (с 16 часов пятницы до 9 часов понедельника плюс 20 часов), т.е. на 85 часов задача запустится, если она войдет в решение в 16 часов ближайшей пятницы, иначе будет ждать следующей; аналогично, на 84 часа есть шанс запустить до 17 часов пятницы и т.д. до 9 часов понедельника;
100 часов - максимальное время, если к выходным добавляются праздничные дни;
Время может быть задано в виде:
    минуты       минуты:секунды      часы:минуты:секунды
    дни-часы     дни-часы:минуты     дни-часы:минуты:секунды

& — позволяет запустить интерактивную задачу в фоновом режиме, при котором пользователю доступна работа в командной строке и одновременно выдача результатов работы интерактивной задачи идет на экран.

Опция -N позволяет задать число узлов (nodes) для задачи, если пользователю это важно:
-N <кол-во узлов>

Для увеличения оперативной памяти можно воспользоваться опциями:
--mem-per-cpu=<MB> — задаёт минимальную память в расчёте на одно ядро в мегабайтах ; если не задано, то по умолчанию 1 ГБ;
 --mem=<MB> — задаёт память на узле в мегабайтах.
Эти опции взаимно исключают друг друга.

Опция --gres с указанием требуемого количества GPU в виде:
--gres=gpu:<кол-во GPU на одном узле>
задаёт запуск программы на узлах с GPU.
Если gres не задан, то количество GPU=0, т.е. GPU при счете не используются.

Опция -p позволяет указать раздел (partition) кластера для запуска задачи:
-p <раздел> или --partition=<раздел>
Если раздел не задан пользователем явно, то по умолчанию будет выбран раздел all, но при отсутствии в нем нужного числа свободных процессоров будут задействованы разделы umt_p2 и apollo.
Список разделов выдается командой sinfo -s , при этом all как раздел по умолчанию помечен *. Разделы all, umt_p2, apollo и debug покрывают весь кластер и взаимно не пересекаются, т.е. содержат разные узлы.
Опция -p debug позволяет запускать задачи в специально выделенном для отладки программ разделе debug с максимальным временем счета 20 минут.
Примеры команд запуска с заданием раздела.
    srun -p debug mytest
    mqrun -np 360 -maxtime 20 -p apollo myprog

или, используя соответствующие опции srun,
    mqrun -n 360 -t 20 -p apollo myprog

Опции mqrun выдаются по команде mqrun -help.

Пример. В результате интерактивного запуска
    srun hostname

выдаётся имя узла, на котором запущен соответствующий процесс, например,
    umt145


При запуске в пакетном режиме команда запуска программы задаётся либо в скрипте, либо через --wrap, например,
    sbatch mybat

или
    sbatch -n 2 --wrap="srun hostname"

где скрипт mybat
#!/bin/sh
#SBATCH -n 2
srun hostname &
wait

Внимание!
Команда srun внутри скрипта может запрашивать ресурсы только в тех пределах, которые установлены командой sbatch.
Скрипт запускается только на первом из выделенных узлов.
Запуск нескольких процессов осуществляется командой srun. При этом все опции, указанные в командной строке или самом скрипте в строках #SBATCH, приписываются к каждой команде srun данного скрипта, если не переопределены в ней. Так, результирующий файл приведённого примера будет содержать 2 строки с именами узлов (возможно, одинаковых), на которых выполнятся 2 процесса задачи, сформированные командой srun.
Если команды srun запускаются в фоновом режиме (символ & в конце строки), то они при наличии ресурсов могут выполняться одновременно.


По умолчанию стандартный вывод пакетной задачи и стандартный поток ошибок направляются в файл с именем slurm-%j.out, где %j заменяется уникальным идентификатором (номером) задачи.

Перенаправление ввода-вывода можно выполнить, указав программе sbatch опции
--error=<filename pattern>, --input=<filename pattern>,
--output=<filename pattern>
.
При задании имени файла (filename pattern) можно использовать символы замены, в частности, %j.

Выдаваемые результаты конкретной команды srun можно поместить вместо стандартного в указанный файл, добавив после команды символ перенаправления вывода (>)
    srun mytest > out_mytest &
Можно (чаще, при интерактивном запуске) параллельно просматривать результаты и сохранять их в файле, например:
    srun --mem 40000 hostname | tee out_hostname

Описание всех опций и примеры команд можно посмотреть в man-руководстве с помощью команд:
    man sbatch
    man srun


Примеры постановки задач в очередь.
u9999@umt:~$ sbatch -n 3 --wrap="srun mytest1 3 5.1"  — сформирована пакетная задача с запуском
                                                                                                3-х процессов mytest1 c 2-мя параметрами;
Submitted batch job 776                                  — задаче присвоен уникальный идентификатор 776;
u9999@umt:~$ srun -N 2 sleep 30 &                — сформирована интерактивная задача в фоновом режиме;
[1] 22313                                     — [1] - номер фоновой задачи в текущем сеансе, 22313 - pid процесса srun на управляющей машине. Уникальный идентификатор можно узнать с помощью команд squeue, sacct.


Информационные команды
     squeue      sacct      sinfo      scontrol      характеристики GPU

squeue — просмотр очереди (информации о задачах, находящихся в счете или в очереди на счет); возможно использование ключей, например:
    squeue --user=`whoami`     — посмотреть только свои задачи;
    squeue --states=RUNNING   — посмотреть считающиеся задачи;
    squeue --long                    — выдать более подробную информацию.

Пример.
u9999@umt:~$ srun -N 2 sleep 30 &
[1] 22313

u9999@umt:~$ squeue

  JOBID PARTITION     NAME     USER    ST    TIME  NODES NODELIST(REASON)
    777     all               sleep      u9999   R     0:23       2      umt[10,15]
JOBID — уникальный идентификатор задачи; никогда не используется повторно ;
PARTITION — название раздела, где считается задача;
NAME — имя задачи пользователя;
USER — логин пользователя;
ST — состояние задачи (R - выполняется, PD - в очереди);
TIME — текущее время счета;
NODES — количество узлов для задачи;
NODELIST(REASON) — список выделенных узлов.

sacct — просмотр задач текущего пользователя за сутки (с начала текущего дня);
возможно использование ключей, например:
     sacct -a --starttime 2011-01-01
     — посмотреть все задачи с начала года.

Пример.
u9999@umt:~$ sacct
       JobID    JobName  Partition    Account  AllocCPUS      State           ExitCode
------------    ---------- ----------   ---------- ------------ ---------------   -----------
522              sbatch      tesla                               2       COMPLETED         0:0
522.batch       batch                                            1       COMPLETED         0:0
777                sleep      all                                   2       CANCELLED+       0:0
780              sbatch      tesla                               2        FAILED               0:0
780.batch       batch                                            1        FAILED            127:0
783                sleep      tesla                               2        RUNNING            0:0

JobID — уникальный идентификатор задачи, повторно не используется;
JobName — имя задачи пользователя;
Partition — название раздела, где считается задача;
State — состояние задачи:   RUNNING — выполняется,
                                           PENDING — ждёт в очереди,
                                           COMPLETED — закончилась,
                                           FAILED — закончилась по ошибке,
                                           CANCELLED+ — снята пользователем;
ExitCode — код возврата.

sinfo — просмотр информации об узлах (прежде всего, о состоянии узлов: доступны, заняты, свободны, ...).
sinfo -s — выдача суммарной информации о разделах кластера без детализации по узлам.

Пример.
u9999@umt:~$ sinfo
PARTITION   AVAIL  TIMELIMIT  NODES   STATE   NODELIST
umt*             up      8:00:00       4         down*   umt[59,92,139,201]
umt*             up      8:00:00     203         idle      umt[1-58,60-91,93-118,120-138,140-200,202-208]
umt*             up      8:00:00       1        down     umt119
tesla               up      8:00:00       1         alloc      tesla2
tesla               up      8:00:00      18         idle       tesla[3-20]
tesla               up      8:00:00       1         down     tesla1

PARTITION — название раздела, где считаются задачи,
                      * - указывает на раздел по умолчанию;
AVAIL — состояние раздела узлов: up - есть доступ, down - нет доступа;
TIMELIMIT — максимальное время, выделяемое для счета задачи;
NODES — количество узлов;
STATE — состояние (в сокращённой форме):
                idle - свободен, alloc - используется процессом, mix - частично занят, частично свободен,
                down, drain, drng - заблокирован,
                comp - все задания, связанные с этим узлом, находятся в процессе завершения;
                * - обозначает узлы, которые в настоящее время не отвечают (not responding);
NODELIST — список узлов.

Пример выдачи sinfo из команд mqinfo и mps:

PARTITION SOCKET CORE CPU THREAD GRES    TIMELIMIT   CPUS(A/I/O/T)
umt           2            4       8      1                      20:00:00   1203/53/408/1664
tesla          2            6       12    1          gpu:8    infinite         322/2/36/360
all*            2            4+     8+   1                      20:00:00   1525/55/444/2024

PARTITION — название раздела: umt, tesla, all; * отмечен раздел по умолчанию;
SOCKET — число процессоров на узле;
CORE — число ядер в процессоре;
CPU — число ядер на узле;
THREAD — число нитей на ядро;
GRES — число общих для узла ресурсов, где gpu - графический ускоритель;
TIMELIMIT — максимальное время, выделяемое для счета задачи;
CPUS(A/I/O/T) — число ядер:
            A (alloc) - заняты, I (idle) - свободны, O (other) - заблокированы, T (total) - всего.

scontrol — выдача детальной информации об узлах, разделах, задачах:

    scontrol show node tesla34 — об узле, в частности, причине состояния drain, down;
    scontrol show partition       — о разделах;
    scontrol show job 174457     — о задаче.


Информацию о технических характеристиках GPU выдает программа pgaccelinfo, которая входит в поставку компилятора PGI. Поэтому предварительно надо установить соответствующий модуль, выполнив команду mpiset, например:
    mpiset 7
    srun --gres=gpu:1 pgaccelinfo

Опция вида -w 'tesla21' позволяет выдать эту информацию для конкретного (в данном случае 21) узла:
    srun -w 'tesla21' --gres=gpu:1 pgaccelinfo


Как удалить задачу
Для отмены выполнения задачи служит команда scancel:

  • Убрать из очереди
        scancel <id1,id2,...,idn> — снимает задачи с уникальными идентификаторами id1,id2,...,idn
        scancel -u u9999 — снимает все задачи пользователя u9999
  • Снять со счёта (выполняется аналогично )
        scancel --state=RUNNING 1,2,3 — снимает со счета уже стартовавшие задачи с идентификаторами 1,2 и 3
        CTRL+C — снимает интерактивную задачу без фонового режима.
  • Пример.
    u9999@umt:~$ squeue
      JOBID PARTITION     NAME     USER     ST       TIME  NODES NODELIST(REASON)
        977     tesla            sleep     u9999    R         1:32      2       tesla[1-2]
    u9999@umt:~$ scancel 977      — сняли со счета интерактивную задачу, считающуюся в фоновом режиме.
    srun: Force Terminated job 977
    u9999@umt:~$ srun: Job step aborted: Waiting up to 2 seconds for job step to finish.
    slurmd[tesla1]: *** STEP 977.0 CANCELLED AT 2011-11-01T18:04:45 ***
    srun: error: tesla1: task 0: Terminated
    srun: error: tesla2: task 1: Terminated
    Enter      — нажать
    [1]+  Exit 15                  srun -p tesla -N 2 sleep 1h
    u9999@umt:~$ squeue
      JOBID PARTITION     NAME     USER  ST       TIME  NODES NODELIST(REASON)
    u9999@umt:~$


    Полезные ссылки

    1. Quick Start User Guide / Slurm, Documentation.
    2. Общие принципы построения системы SLURM. Берсенев А.Ю. / Семинар ОСО, 13.04.2011.
    3. Обзор планировщиков для SLURM. Берсенев А.Ю. / Семинар ОСО, 20.04.2011.
    4. Оптимизация управления ресурсами суперкомпьютеров с помощью SLURM. M. Тим Джонс, 18.10.2012.
    5. Инструкция Slurm для пользователя. Краткое руководство по запуску / Суперкомпьютер ИК НАН Украины
    6. Берсенёв А.Ю. Шарф С.В. "О системе SLURM и изменениях в обслуживании очереди задач"/ Семинар ОСО, 25.04.2013 - Видеоархив УрО РАН: http://uran.vidicor.ru/vod/?id=2013_UrORAN_25_04_2013_slurm

     

    Команда module - выбор окружения для решения задачи

    При работе на кластерах можно использовать различные компиляторы, библиотеки обмена сообщениями и пакеты прикладных программ (приложения), поэтому пользователь должен определить среду для решения своей задачи, выбрав нужное программное обеспечение. Выбор определяется модулем установки переменных окружения, требуемых для работы программы. Названия модулей содержат имена компиляторов, библиотек, пакетов, номера версий. Например, при загрузке модуля openmpi/intel64 программа пользователя будет откомпилирована 64-разрядным компилятором intel с библиотекой openmpi.

    Список загруженных на настоящий момент модулей можно выдать с помощью команды module list.
    Сервисная команда mpiset служит для быстрой смены модуля, задающего компилятор и версию библиотеки MPI.

    Списки доступных модулей на кластерах могут отличаться и пополняться с введением нового программного обеспечения.
    Пример. Список модулей, доступных на кластере umt на 01.07.2011, выданный с помощью команды module avail
            OpenFoam/1.7.x                        matlab/R2010b                        openmpi/gcc64                         
             dvm/current                              mpi/default                              openmpi/intel64
             firefly/71g-openmpi                   music/4.0                                paraview/3.10
             matlab/R2010a                         mvapich2/intel64                     towhee/6.2.15


    В целом, работа с модулями обеспечивается командой module.

    • module avail - выдача списка доступных модулей
    • module load < имя модуля из списка > - загрузка модуля, выполняется из командной строки или из конфигурационного файла, настроит Вашу окружающую среду так, чтобы приложение могло использоваться;
    • module unload < имя загруженного модуля > - выгрузка модуля отменит настройки переменных окружения, задаваемых данным модулем; 
    • module switch < имя загруженного модуля > < имя модуля > - замена загруженного модуля (первого) на указанный модуль (второй);
    • module list - выдача списка загруженных (на данный момент) модулей;
    • module show  < имя модуля из списка > - вывод полного имени файла с описанием команд изменения окружения, выполняемых при загрузке модуля;
    • module display  < имя модуля из списка > вывод полного имени файла с описанием модуля как и в команде module show;
    • module whatis  < имя модуля из списка >  вывод на экран компилятора, библиотеки, приложения, устанавливаемых данным модулем;
    • module whatis   вывод на экран списка модулей и соответствующих модулям настроек компилятора, библиотеки, приложения;
    • module clear  выгрузка всех загруженных  модулей на текущий момент.

    Внимание!
    1. Настройка с помощью команд mpiset или module имеет силу на текущий сеанс работы на кластере.
    2. Для того, чтобы не настраивать заново в начале каждого сеанса работы среду для решения своей задачи, можно нужные настройки сохранить в $HOME/.bash_profile пользователя, используя следующие команды:

    • module initadd  < имя модуля из списка доступных>  меняет $HOME/.bash_profile , загружая указанный модуль для следующих сеансов работы;
    • module initlist  - выдача списка загруженных в $HOME/.bash_profile модулей для следующих сеансов работы;
    • module initclear - чистит $HOME/.bash_profile, оставляя лишь модуль null, который не содержит никаких настроек.

    Команда mpiset - выбор версии MPI и компилятора

    Для выбора компиляторов, библиотек обмена сообщениями и пакетов прикладных программ, необходимых для работы программы пользователя, используются модули установки переменных окружения.

    Команда mpiset позволяет выбрать модуль из списка основных модулей, задающих компилятор и версию библиотеки MPI.

    Команда mpiset без параметров выдает пронумерованый список доступных вариантов.
    Строка, помеченная словом active, указывает на текущие настройки.

    Для смены модуля (библиотеки MPI, компилятора) необходимо выполнить команду
        mpiset  <n>
    где <n> – номер варианта настроек для данного кластера.

        ВНИМАНИЕ!

    • Список вариантов на каждом вычислительном кластере свой.
    • Настройки по умолчанию на кластерах могут не совпадать.
    • Команды mpiset и mpiset <n>  выполняются из командной строки и не работают, если загружен Midnight Commander (mc).

    Пример. Список основных вариантов настроек, полученный в начале сеанса 28.12.2016 командой mpiset на umt
         active  1       MVAPICH2 Intel 14.0, mvapich2/intel64
                    2       OpenMPI Intel 11.1, openmpi/intel64
                    3       OpenMPI 32bit GCC 4.4, openmpi/gcc32
                    4       OpenMPI 32bit Intel 14.0, openmpi/intel32
                    5       OpenMPI GCC v4.4, openmpi/gcc64
                    6       OpenMPI v1.10 GCC 4.8, openmpi/gcc64_1.10
                    7       MVAPICH2 2.1 PGI 16.5, mvapich2/pgi_16.5

    Опции компиляторов

    Компилятор G77

    Компилятор G77 (GNU Fortran) основан на стандарте ANSI Fortran 77, но он включает в себя многие особенности, определенные в стандартах Fotran 90 и Fortran 95.

    Синтаксис команды:

           g77 [-c?-S?-E]
               [-g] [-pg] [-Olevel]
               [-Wwarn...] [-pedantic]
               [-Idir...] [-Ldir...]
               [-Dmacro[=defn]...] [-Umacro]
               [-foption...] [-mmachine-option...]
               [-o outfile] infile...

     Все опции поддерживаемые gcc  поддерживаются и g77. Компиляторы С и g77 интегрированы.

    Обращение:

    g77 [option | filename]...

    Исходные файлы:

    source.f,source.for, source.FOR

    Значение некоторых опций:

    -c создать только объектный файл (source.o) из исходного ( source.f, .source.for, source.FOR )
    -o file создать загрузочный файл с именем file (по умолчанию создается файл с именем a.out)
    -llibrary использовать библиотеку liblibrary.a при редактировании связей
    -Idir добавить каталог dir в список поиска каталогов, содержащих include- файлы 
    -Ldir добавить директорию dir в список поиска библиотек
    -O включить оптимизацию
    -g создать отладочную информацию для работы с отладчиком

    Для получения полного описания g77 следует смотреть документацию по GNU Fortran. Об опциях g77 можно также получить информацию с помощью команд:

    info g77
    man g77

    Компилятор GCC

    GСС - это свободно доступный оптимизирующий компилятор для языков C, C++.

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

    Файлы с расширением .cc или .C рассматриваются, как файлы на языке C++, файлы с расширением .c как программы на языке C, а файлы c расширением .o считаются объектными.
     
    Чтобы откомпилировать исходный код C++, находящийся в файле F.cc, и создать объектный файл F.o, необходимо выполнить команду:

    gcc -c F.cc

    Опция –c означает «только компиляция».

    Чтобы скомпоновать один или несколько объектных файлов, полученных из исходного кода - F1.o, F2.o, ... - в единый исполняемый файл F, необходимо ввести команду:

    gcc -o F F1.o F2.o

    Опция -o задает имя исполняемого файла.

    Можно совместить два этапа обработки - компиляцию и компоновку - в один общий этап с помощью команды:

    gcc -o F <compile-and-link-options> F1.cc ... -lg++ <other-libraries>

    <compile-and-link –options> - возможные дополнительные опции компиляции и компоновки. Опция –lg++ указывает на необходимость подключить стандартную библиотеку языка С++, <other-libraries> - возможные дополнительные библиотеки.
    После компоновки будет создан исполняемый файл F, который можно запустить с помощью команды ./F <arguments>. Строка <arguments> определяет аргументы командной строки Вашей программы.
    В процессе компоновки очень часто приходится использовать библиотеки. Библиотекой называют набор объектных файлов, сгруппированных в единый файл и проиндексированных. Когда команда компоновки обнаруживает некоторую библиотеку в списке объектных файлов для компоновки, она проверяет, содержат ли уже скомпонованные объектные файлы вызовы для функций, определенных в одном из файлов библиотек. Если такие функции найдены, соответствующие вызовы связываются с кодом объектного файла из библиотеки. Библиотеки могут быть подключены с помощью опции вида -lname. В этом случае в стандартных каталогах, таких как /lib , /usr/lib, /usr/local/lib будет проведен поиск библиотеки в файле с именем libname.a. Библиотеки должны быть перечислены после исходных или объектных файлов, содержащих вызовы к соответствующим функциям.

    Опции компиляции

    Среди множества опций компиляции и компоновки наиболее часто употребляются следующие:

      Опция   Назначение
    -c Эта опция означает, что необходима только компиляция. Из исходных файлов программы создаются объектные файлы в виде name.o. Компоновка не производится.
    -Dname=value Определить имя name в компилируемой программе, как значение value. Эффект такой же, как наличие строки #define name value в начале программы. Часть =value может быть опущена, в этом случае значение по умолчанию равно 1.
    -o file-name Использовать file-name в качестве имени для создаваемого файла.
    -lname Использовать при компоновке  библиотеку libname.so
    -Llib-path
    -Iinclude-path
    Добавить к стандартным каталогам поиска библиотек и заголовочных файлов пути lib-path и include-path соответственно.
    -g Поместить в объектный или исполняемый файл отладочную информацию для отладчика gdb. Опция должна быть указана и для компиляции, и для компоновки. В сочетании –g рекомендуется использовать опцию отключения оптимизации –O0 (см.ниже)
    -MM Вывести зависимости от заголовочных файлов ,  используемых в Си или С++ программе, в формате, подходящем для утилиты   make. Объектные или исполняемые файлы не создаются.
    -pg Поместить в объектный или исполняемый файл инструкции профилирования для генерации информации, используемой утилитой gprof. Опция должна быть указана и для компиляции, и для компоновки. Собранная с опцией -pg программа при запуске генерирует файл статистики. Программа gprof на основе этого файла создает расшифровку, указывающую время, потраченное на выполнение каждой функции.
    -Wall Вывод сообщений о всех предупреждениях или ошибках, возникающих во время компиляции программы.
    -O1
    -O2
    -O3
    Различные уровни оптимизации.
    -O0 Не оптимизировать. Если вы используете многочисленные -O опции с номерами или без номеров уровня, действительной является последняя такая  опция.
    -I Используется для добавления ваших собственных каталогов для поиска заголовочных файлов в процессе сборки
    -L Передается компоновщику. Используется для добавления ваших собственных каталогов для поиска библиотек в процессе сборки.
    -l Передается компоновщику. Используется для добавления ваших собственных библиотек для поиска в процессе сборки.

    Компилятор GFortran

    GFortran - это название компилятора языка программирования Фортран, входящего в коллекцию компиляторов GNU.

    Сборка FORTRAN-программы:
    Синтаксис

    gfortran [-c?-S?-E]
                 [-g] [-pg] [-Olevel]
                 [-Wwarn...] [-pedantic]
                 [-Idir...] [-Ldir...]
                 [-Dmacro[=defn]...] [-Umacro]
                 [-foption...]
    [-mmachine-option...]
                 [-o outfile] infile...

    GFortran опирается на GCC, и, следовательно, разделяет большинство его характеристик. В частности, параметры для оптимизации и генерации отладочной информации у них совпадают.
    GFortran используется для компиляции исходного файла, source.f90, в объектный файл, object.o или исполняемый файл, executable. Одновременно он генерирует модуль файлов описания встречающихся модулей, так называемый  nameofmodule.mod.

    Для компиляции исходного файла source.f90, можно  запустить: gfortran source.f90

    Выходной файл будет автоматически имени source.o. Это объектный файл, который не может быть исполнен. После того как вы собрали некоторые исходные файлы, вы можете соединить их вместе с необходимыми библиотеками для создания исполняемого файла. Это делается следующим образом: gfortran -o executable object1.o object2.o..., где исполняемым будет executable, objectX.o - объектные файлы, которые могут быть созданы, как указано выше, или в равной степени другими компиляторами  из источников в другом языке. Если  опущено имя  исполняемого файла, то  исполняемый файл будет с названием a.out. Исполняемый файл может быть выполнен, как и в любой другой программе. Можно также пропустить отдельный этап компиляции и ввести такую команду: gfortran o executable source1.f90 source2.f90, которая будет осуществлять сбор исходных файлов source1.f90 и source2.f90, связь и создаст исполняемый файл. Вы также можете поместить объектные  файлы в этой командной строке, они будут автоматически присоединены.

    Опции компилятора GFortran

      Опция   Назначение
    -c Эта опция означает, что необходима только компиляция. Из исходных файлов программы создаются объектные файлы в виде name.o. Компоновка не производится.
    -Dname=value Определить имя name в компилируемой программе, как значение value. Эффект такой же, как наличие строки #define name value в начале программы. Часть =value может быть опущена, в этом случае значение по умолчанию равно 1.
    -o file-name Использовать file-name в качестве имени для создаваемого файла.
    -lname Использовать при компоновке  библиотеку libname.so
    -Llib-path
    -Iinclude-path
    Добавить к стандартным каталогам поиска библиотек и заголовочных файлов пути lib-path и include-path соответственно.
    -g Поместить в объектный или исполняемый файл отладочную информацию для отладчика gdb. Опция должна быть указана и для компиляции, и для компоновки. В сочетании –g рекомендуется использовать опцию отключения оптимизации –O0 (см.ниже)
    -MM Вывести зависимости от заголовочных файлов ,  используемых в Си или С++ программе, в формате, подходящем для утилиты   make. Объектные или исполняемые файлы не создаются.
    -pg Поместить в объектный или исполняемый файл инструкции профилирования для генерации информации, используемой утилитой gprof. Опция должна быть указана и для компиляции, и для компоновки. Собранная с опцией -pg программа при запуске генерирует файл статистики. Программа gprof на основе этого файла создает расшифровку, указывающую время, потраченное на выполнение каждой функции.
    -Wall Вывод сообщений о всех предупреждениях или ошибках, возникающих во время компиляции программы.
    -O1
    -O2
    -O3
    Различные уровни оптимизации.
    -O0 Не оптимизировать. Если вы используете многочисленные -O опции с номерами или без номеров уровня, действительной является последняя такая  опция.
    -I Использует для добавления ваших собственных каталогов  поиска заголовочных файлов в процессе сборки
    -L Передает компоновщику. Использует для добавления ваших собственных каталогов  поиска библиотек в процессе сборки.
    -l Передает компоновщику. Использует для добавления ваших собственных библиотек  поиска в процессе сборки.

    Компилятор PGCC

    Компилятор Portland Group C (PGCC).

    Компилятор PGCC для процессоров AMD64 и IA32/EM64T производит компиляцию программ C и линкует согласно опциям в командной строке.

    Синтаксис команды:

    pgcc [ -параметры ]... sourcefile...

     

    • Параметры могут отсутствовать или содержать опции копилятора
    • Суффиксы sourcefile указывают на вид файла:
           .c   - файл на C; обрабатывается препроцессором перед компиляцией; компилируется
           .i   - файл на C после обработки препроцессора; компилируется
           .s   - ассемблерный файл; передаётся ассемблеру
           .S   - ассемблерный файл; обрабатывается препроцессором; передаётся ассемблеру
           .o   -объектный файл; передаётся компоновщику
           .a   - библиотечный файл; передаётся компоновщику

    Полный список опций компилятора можно посмотреть по команде man pgcc.
    Некоторые важные опции компиляции для PGCC приведены ниже:

      Опция   Назначение
    Эта опция означает, что необходима только компиляция. Из исходных файлов программы создаются объектные файлы.
    -C Включает  проверки выхода индекса за границы массива
    -O0 Отключает оптимизацию.
    -О1 Оптимизация по размеру. Не использует методов оптимизации, которые могут увеличить размер кода. Создает в большинстве случаев самый маленький размер кода.
    -O2 или -O Оптимизация устанавливаемая по умолчанию.
    -O3 Задействует методы оптимизации из -O2 и, дополнительно, более агрессивные методы оптимизации, которые подходят не для всех программ.
    -Os Включает оптимизацию по скорости, но при этом отключает некоторые оптимизации, которые могут привести к увеличению размеров кода при незначительном выигрыше в скорости.
    -fast Включает в себя -O2 и ряд других опций, таких как использование векторизации с поддержкой SSE инструкций. Использование -fast понижает точность вычислений.
    -g Включает информацию об отладке.
    -fastsse То же самое что и -fast -Mipa=fast - включает межпроцедурный анализ.
    -I Использует для добавления ваших собственных каталогов  поиска заголовочных файлов в процессе сборки.
    -L Передает компоновщику. Использует для добавления ваших собственных каталогов  поиска библиотек в процессе сборки.
    -l Передает компоновщику. Использует для добавления ваших собственных библиотек  поиска в процессе сборки.

    Компилятор PGFortran

    Компилятор The Portland Group Inc. Fortran (PGFortran).

    Компилятор PGFortran  для процессоров AMD64 и IA32/EM64T производит компиляцию программ на Фортране и линкует согласно опциям в командной строке. PGFortran является интерфейсом для компиляторов pgf90 и pgf95.

    Синтаксис команды:

    pgfortran [ -параметры ]... sourcefile...

    • Параметры могут отсутствовать или содержать опции копилятора
    • Суффиксы sourcefile указывают на вид файла:
           .f     - файл на Фортране  с фиксированным форматом; компилируется
           .F     - файл на Фортране с фиксированным форматом; после обработки препроцессором -  компилируется
           .f90   - файл на Фортране в свободном формате; компилируется
           .F90   - файл на Фортране в свободном формате; после обработки препроцессором - компилируется
           .f95   -  файл на  Фортране в свободном формате; компилируется
           .F95   -  файл на  Фортране в свободном формате; после обработки препроцессором - компилируется
           .for   - файл на Фортране  с фиксированным форматом; компилируется
           .FOR  - файл на Фортране с фиксированным форматом; после обработки препроцессором - компилируется
           .fpp   - файл на Фортране с фиксированным форматом; после обработки препроцессором -  компилируется
           .s     - ассемблерный файл; передаётся ассемблеру
           .S     - ассемблерный файл; обрабатывается препроцессором; передаётся ассемблеру
           .o     - объектный файл; передаётся компоновщику
           .a     - библиотечный файл; передаётся компоновщику

    Полный список опций компилятора можно посмотреть по команде man pgfortran.
    Некоторые важные опции компиляции для PGFortran приведены ниже:

    Опции компилятора PGFortran

      Опция   Назначение
    -o file

    Использует file как имя выходного исполняемого файла программы, вместо имени по умолчанию - a.out. Если используется совместно с опцией или -S и с одним  входным  файлом, то file используется в качестве имени объектного или ассемблерного выходного файла.

    -S

    Пропускает этапы ассемблирования и линкования. Для каждого файла с именем, например, file.f создает при выходе из компиляции  файл с именем file.s . См. также .

    -fastsse

    Выбирает основные  оптимальные установки для  процессора, который поддерживает SSE инструкции (Pentium 3 / 4, AthlonXP / MP, Opteron) и SSE2 (Pentium 4, Opteron). Используйте в  pgf90 -fastsse  -help чтобы просмотреть установки.

    -C Включает  проверки выхода индекса за границы массива также как и -Mbounds
    -i2 Целые и логические переменные длиной 2 байта .
    -i4 Целые и логические переменные длиной 4 байта .
    -i8 Целые и логические переменные длиной 8 байт . Устанавливается по умолчанию. Для операций над целыми числами отводится 64 бита.
    -O[N] Устанавливает уровень оптимизации равным N. -O0 до -O4по умолчанию устанавливается  -O2.
    Если не указана опция -O и если не заказана -g, то устанавливается -O1 , но если заказана -g, то устанавливается -O0. Когда номер у -O не указан, то устанавливается -O2.
    -O0 Без оптимизации.
    -О1

    Оптимизация  в рамках основных блоков. Выполняется некоторое распределение регистров.  Глобальная оптимизация не выполняется.

    -O2 Выполняется оптимизация -O1. Кроме того, выполняются традиционные скалярные оптимизации, такие как признание индукции и инвариант цикла движения глобального оптимизатора.
    -O3

    Задействует методы оптимизации из -O1 и -O2 и, дополнительно, более агрессивные методы оптимизации циклов и доступа к памяти, такие как подстановка скаляров, раскрутка циклов. Эти агрессивные методы оптимизации могут, в ряде случаев, и замедлить работу приложений .

    -O4  Выполняет все уровни оптимизации -O1,-O2, -O3, кроме того, выполняет  оптимизацию  выражений с плавающей точкой.
    -fpic

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

    -gopt

    Сообщает компоновщику включение отладочной информации без отключения оптимизации

    -s

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

    -pg Устанавливает  профилирование; влечёт   установку -Mframe
    -r4 Переменные DOUBLE PRECISION рассматриваются как REAL.
    -r8 Переменные REAL  рассматриваются как  DOUBLE PRECISION  . Это тоже самое, что и указать -Mr8 и -Mr8intrinsics.
    -fast Обеспечивает ускоренный метод   нескольких оптимизаций на время выполнения программы.
    Устанавливает параметры для повышения производительности в размере не менее 2, см.-O. Используйте pgf90 -fast -help для просмотра эквивалентных переключателей.
    -g Создаёт отладочную информацию. Опция устанавливает уровень оптимизации до нуля, если только заказана опция -O . Процесс может привести к неожиданным результатам, если заказан уровень оптимизации отличный от нуля. Сгенерированный код будет работать медленнее при -O0, чем при других уровнях оптимизации.
    -I Добавляет ваши собственные каталоги  поиска заголовочных файлов в процессе сборки
    -L Передает компоновщику. Добавляет ваши собственные каталоги  поиска библиотек в процессе сборки.
    -l Передает компоновщику. Добавляет ваши собственные библиотеки   поиска в процессе сборки.

    Опции компилятора ICC

    icc -команда для вызова компилятора Intel(R) (C или C++).

    Синтаксис команды:
    icc [параметры] file1 [file2] ...
         

    • параметры  могут отсутствовать или содержать опции компилятора
    • fileN – это файлы на языке  C или C++, сборочные файлы, объектные файлы, библиотеки объектов или другие линкуемые  файлы

       

    Полный список опций можно посмотреть по команде man icc .

    Некоторые важные опции компиляции для ICC приведены ниже:

      Опция   Назначение
    Эта опция означает, что необходима только компиляция. Из исходных файлов программы создаются объектные файлы
    -C Включает  проверки выхода индекса за границы массива
    -O0 Отключает оптимизацию
    -О1 Оптимизация по размеру. Не использует методов оптимизации, которые могут увеличить размер кода. Создает в большинстве случаев самый маленький размер кода.
    -O2 или -O Оптимизация устанавливаемая по умолчанию.
    -O3 Задействует методы оптимизации из -O2 и, дополнительно, более агрессивные методы оптимизации, которые подходят не для всех программ.
    -Os Включает оптимизацию по скорости, но при этом отключает некоторые оптимизации, которые могут привести к увеличению размеров кода при незначительном выигрыше в скорости.
    -fast Обеспечивает ускоренный метод для  нескольких оптимизаций на время выполнения программы.
    Устанавливает -xT -O3 -ipo -no-prec-div -static параметры для повышения производительности:
    • -O3 (см. выше)
    • -ipo (включает межпроцедурную оптимизацию между файлами)
    • -static (предотвращает линкование с общими библиотеками). 
    Параметры задаются списком и не могут быть заданны по отдельности.
    -g Включает информацию об отладке
    -I Использует для добавления ваших собственных каталогов  поиска заголовочных файлов в процессе сборки
    -L Передает компоновщику. Использует для добавления ваших собственных каталогов  поиска библиотек в процессе сборки.
    -l Передает компоновщику. Использует для добавления ваших собственных библиотек  поиска в процессе сборки.

    Опции компилятора Intel Fortran

    ifort -команда для вызова компилятора Intel(R) Fortran.

    Синтаксис команды:
    ifort [параметры] file1 [file2] ...

    • параметры  могут отсутствовать или содержать опции компилятора
    • fileN – это файлы на языке  Fortran, сборочные файлы, объектные файлы, библиотеки объектов или другие линкуемые  файлы

    Полный список опций можно посмотреть по команде man ifort .

    Команда ifort интерпретирует входные файлы по суффиксу имени файла следующим образом:
    Имена файлов с суффиксом .f90 интерпретируются как файлы в свободной форме записи  на Fortran 95/90.
    Имена файлов с суффиксом .f, .for или .ftn интерпретируются как фиксированная форма записи для  Fortran  66/77  файлов.

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

    Некоторые важные опции компиляции для Intel Fortran приведены ниже:

      Опция   Назначение
    -free Указывает, что исходные файлы находятся в свободном формате.
    По умолчанию, формат исходного файла определяется суффиксом файла
    -fixed Указывает, что  исходные файлы находятся в фиксированном формате. По умолчанию, формат исходного файла определяется суффиксом файла
    Эта опция означает, что необходима только компиляция. Из исходных файлов программы создаются объектные файлы
    -C Включает  проверки выхода индекса за границы массива
    -i2 Целые и логические переменные длиной 2 байта (тоже, что и опция -integer-size 16). По умолчанию целочисленный размер равен 32 разряда.
    -i4 Целые и логические переменные длиной 4 байта (тоже, что и опция -integer-size 32 ). Это значение устанавливается по умолчанию.
    -i8 Целые и логические переменные 8 байт (тоже ,  что и опция -integer-size 64). По умолчанию целочисленный размер равен 32 разряда.
    -O0 Отключает оптимизацию
    -О1 Оптимизация по размеру. Не использует методов оптимизации, которые могут увеличить размер кода. Создает в большинстве случаев самый маленький размер кода.
    -O2 или -O Максимизация скорости. Как правило, создает более быстрый код, чем -O1. Эта опция устанавливается по умолчанию для оптимизации, если не указана  -g
    -O3 Задействует методы оптимизации из -O2 и, дополнительно, более агрессивные методы оптимизации циклов и доступа к памяти, такие как подстановка скаляров, раскрутка циклов, подстановка кода для избегания ветвлений, блокирование циклов для обеспечения более эффективного использования кэш-памяти и, только на системах архитектуры IA-64, дополнительная подготовка данных. Данная опция особенно рекомендуется для приложений, где есть циклы, которые активно используют вычисления с плавающей точкой или обрабатывают большие порции данных. Эти агрессивные методы оптимизации могут в ряде случаев, и замедлить работу приложений других типов по сравнению с использованием -O2.
    -OpenMP Включает поддержку стандарта OpenMP 2.0
    Распараллеливает программу. Позволяет параллелизацию для создания многопоточного кода на основе команд OpenMP. Этот опция  может быть выполнена в параллельном режиме  на однопроцессорных и многопроцессорных системах. OpenMP-опция работает как с-O0 (без оптимизации) и c любым уровнем оптимизации -O. Указание с-O0 помогает для отладки OpenMP приложений.
    -OpenMP-stubs Включает выполнение программ OpenMP в последовательном режиме. Директивы OpenMP игнорируются, если стоят заглушки (stubs) для OpenMP
    -p Порождает дополнительный код для записи профилирующей информации, подходящей  для  анализирующей  программы PROF. Вы должны использовать эту опцию при компиляции исходного файла, о котором вы хотите получить информацию, и вы также должны использовать ее при линковке.
    -parallel Включает автоматическое распараллеливание   циклов, для которых это  безопасно. Чтобы использовать эту опцию, вы также должны указать-O2 и-O3.
    -r8 Вещественные  и комплексные переменные длиной  8 байт. Переменные REAL рассматриваются как DOUBLE PRECISION (REAL(KIND=8)) и комплексные  рассматриваются в качестве DOUBLE COMPLEX (COMPLEX(KIND=8)). Это тоже самое, что и указать -real-size 64  или -autodouble.
    -r16 Вещественные и комплексные переменные  длиной 16 байт. Переменные REAL  рассматриваются как  REAL (REAL(KIND=16), COMPLEX и DOUBLE COMPLEX  рассматривается как COMPLEX (COMPLEX(KIND=16)). Это тоже самое, что и указать -real-size 128.
    -save Сохраняет  переменные, за исключением тех, которые объявлены, как AUTOMATIC, в статической памяти (тоже, что и  noauto-noautomatic). По умолчанию используется –autoscalar, однако, если Вы укажите -recursive или -OpenMP, то по умолчанию используется AUTOMATIC
    -stand Заставляет компилятор выдавать   сообщения компиляции для нестандартных элементов языка.
    -fast Обеспечивает ускоренный метод для  нескольких оптимизаций на время выполнения программы.
    Устанавливает следующие параметры для повышения производительности:
    • -O3
    • -ipo (включает межпроцедурную оптимизацию между файлами)
    • -static (предотвращает линкование с общими библиотеками).
    -g Помещает в объектный или исполняемый файл отладочную информацию для отладчика gdb. Опция должна быть указана и для компиляции, и для компоновки. В сочетании –g рекомендуется использовать опцию отключения оптимизации –O0
    -check bounds Выполняет динамическую проверку выхода индекса за границы массива. Проверка может увеличить время выполнения программы.
    -I Использует для добавления ваших собственных каталогов  поиска заголовочных файлов в процессе сборки
    -L Передает компоновщику. Использует для добавления ваших собственных каталогов  поиска библиотек в процессе сборки.
    -l Передает компоновщику. Использует для добавления ваших собственных библиотек  поиска в процессе сборки.

    Использование GPU на кластере, CUDA

    На кластере "Уран" (umt) введены в эксплуатацию вычислительные узлы, оснащенные ускорителями NVIDIA Tesla. На одном узле может быть одновременно запущено до 8 задач, каждой из которых выделяется один или несколько графических процессоров.

    Для работы с GPU можно использовать
    1) технологию CUDA;
    2) pragma-программирование, предоставляемое С- и Fortran-компиляторами PGI (например, директивы OpenACC);
    3) систему Matlab.
    Запуск задач на графических процессорах осуществляется в системе SLURM (см. Запуск задач на кластере в системе SLURM) с использованием команды запуска с опцией --gres=gpu:N.
    Компиляция и запуск приложений для GPU с PGI Accelerator и OpenACC, а также запуск программ с использованием GPU в системе Matlab рассматриваются в отдельных инструкциях.
    Ниже рассматривается компиляция программ и технология CUDA.

                                          Компиляция программ и технология CUDA

    Свежая версия библиотеки CUDA находится в каталоге /opt/cuda/.

      /opt/cuda/include/ — заголовочные файлы;
      /opt/cuda/lib /— библиотека CUDA;
      /opt/cuda/doc/ — документация.
    Чтобы использовать библиотеку CUDA, необходимо при компиляции программы заказать данную библиотеку, например:
        gcc mytest.c -o mytest -lcuda -L/opt/cuda/lib -I/opt/cuda/include

    Можно использовать компилятор nvcc:
        nvcc <имя файла для компиляции> -o <имя выходного файла>

    На кластере "Уран" при выполнении данной команды по умолчанию подключается библиотека CUDA . Можно компилировать программы на языках C и C++ (файлы с расширением .c и .cpp) и программы, написанные с использованием технологии CUDA (файлы с расширением .cu), например:
    u9999@umt:~$ nvcc main.c -o gputest

    Пример
    Пусть файл cuda_test.cu (из домашнего каталога) содержит программу на CUDA:
    #include <cuda.h>
    #include <stdio.h>
    int main() {
      int GPU_N;
      int dev;
      cudaGetDeviceCount(&GPU_N);
      printf("Device count: %d\n", GPU_N);
      for(dev=0;dev<GPU_N;dev++) {
        cudaDeviceProp deviceProp;
        cudaGetDeviceProperties(&deviceProp, dev);
        printf("PCI Bus id: %d\n",deviceProp.pciBusID);
      }
      return 0;
    }

    Тогда компиляция программы и запуск задачи на кластере могут иметь вид:
    u9999@umt:~$ nvcc cuda_test.cu -o cuda_test
    u9999@umt:~$ srun --gres=gpu:1 ./cuda_test
    Device count: 1
    PCI Bus id: 8
    u9999@umt:~$ srun --gres=gpu:2 ./cuda_test
    Device count: 2
    PCI Bus id: 10
    PCI Bus id: 26

    Поддержка CUDA есть в компиляторе Portland Group.
    Инструкции по использованию CUDA в Фортране можно найти на сайте Portland Group (http://www.pgroup.com/resources/cudafortran.htm).
    Для компиляции Fortran-программы с CUDA следует установить переменные окружения командой module или mpiset, выбрав связку MVAPICH+PGI, например:
        module switch mpi/default mvapich2/pgi_12.10

    или соответственно
        mpiset 7

    и откомпилировать программу компилятором pgfortran с опцией -Mcuda, указав при необходимости оптимизированные библиотеки, например:
        pgfortran -o mytest test.cuf -Mcuda -lcublas

    Ссылки на руководства по CUDA

    Сообщество пользователей CUDA ВМК МГУ (выложены лекции в виде слайдов и есть активный форум, на котором можно задавать вопросы по CUDA. В работе форума активно участвуют сотрудники Nvidia)
    https://sites.google.com/site/cudacsmsusu/home

    CUDA zone: сборник приложений на CUDA, многие с документацией и исходными кодами
    http://www.nvidia.ru/object/cuda_apps_flash_new_ru.html#state=home

    Записи семинаров по CUDA:
    a) введение в CUDA
    http://www.gotdotnet.ru/blogs/parallel-computing/9966/
    b) библиотеки с поддержкой CUDA
    http://www.gotdotnet.ru/blogs/parallel-computing/10070/
    c) отладка и профилировка CUDA приложений
    http://www.gotdotnet.ru/blogs/parallel-computing/10362/

    Чтобы быстро задействовать GPU (хотя и с меньшей эффективностью) можно использовать директивные средства распараллеливания, а именно PGI Accelerator, доступ к триальной версии которого можно получить на месяц бесплатно
    http://www.nvidia.ru/object/openacc-gpu-directives-ru.html

    вот ссылки на записи презентаций по применению данного ПО для C и Fortran кодов
    http://youtu.be/5tDhWkSc4BI
    http://youtu.be/MjGEcZ7LHAQ

    25 июня по 7 июля 2012 в Москве в МГУ будет проходить Международная Летняя Суперкомпьютерная Академия, на которой будут курсы по CUDA.
    http://academy.hpc-russia.ru/

    О запуске приложений с OpenMP, PGI Accelerator и OpenACC

    О компиляторах

    Пользователям доступны компиляторы GNU, Intel и PGI, поддерживающие языки C, C++ и Fortran.
    Смена компилятора осуществляется командой module или mpiset, например, для работы с PGI на umt можно выполнить
        mpiset 7

    После такой установки команды вида mpicc, mpif77 и т.п. можно использовать вместо имен компиляторов, даже если программа не использует MPI.

    Об опциях компилятора можно узнать с помощью команд man или info, например,
        man pgcc
        info pgСС


    Приложения с OpenMP (Компиляция Запуск)

    Приложения с OpenMP можно запускать на кластере "Уран" (umt).

    Приложения с OpenMP могут быть запущены как на обычных вычислительных узлах umt, так и на узлах с графическими ускорителями и большим объёмом оперативной памяти.

    OpenMP подключается опцией, соответствующей установленному компиляторy (http://openmp.org/wp/openmp-compilers/):

     gcc/gfortran                  -fopenmp           GNU
     icc/ifort                     -openmp            Intel (по умолчанию на umt)
     pgcc/pgCC/pgf77/pgfortran     -mp                PGI
    

    Так, компиляция файла exam.c на umt компилятором Intel (с учетом умолчания) выполняется командой
        icc -openmp exam.c -o exam_i

    или командой
        mpicc -openmp exam.c -o exam_i


    Число параллельных нитей задается с помощью переменной окружения OMP_NUM_THREADS. Как правило, она устанавливается перед запуском программы из командной строки командой вида
        export OMP_NUM_THREADS=8

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

    Запуск приложения. Пользователю необходимо указать число ядер (cpus) для каждого из процессов (task) с помощью опции
    --cpus-per-task=ncpus
    ( см., например, команду man srun).

    При этом система предоставляет узел для процесса, если на нем имеется указанное число свободных ядер.
    Максимальное число ядер, равное 36, содержат узлы раздела apollo (см. Кластер "Уран").

    Пусть задано
        export OMP_NUM_THREADS=12

    Тогда в результате выполнения команды интерактивного запуска
        srun --cpus-per-task=6 exam_i > exam_i.out

    одному (n=1 по умолчанию) процессу (задаче) пользователя будет выделено 6 ядер на узле и при вычислениях будет задействовано 12 нитей; результаты вычислений будут записаны в указанный пользователем файл exam_i.out

    Внимание! Опция --mem=<MB> задает запуск на узле с большей памятью.
    Например, команда
        srun --mem=40G --cpus-per-task=12 exam_i > exam_i.out

    запустит задачу на узле с оперативной памятью не меньшей, чем 48 ГБ (о типах узлов см. Кластер "Уран").
    В пакетном режиме соответствующий запуск может выглядеть так:
        sbatch --mem=40G --cpus-per-task=12 mybat_i

    где файл mybat_i содержит строки
    #!/bin/sh
    srun exam_i > exam_i.out

    Если файл mybat_i не содержит перенаправления вывода, т.е. имеет вид
    #!/bin/sh
    srun exam_i

    то результаты вычислений по умолчанию будут записаны в файл slurm-<id>.out (<id> - уникальный номер или уникальный идентификатор задачи, см. Запуск задач на кластере в системе SLURM).

    В командах, представленных выше, в качестве примера программы можно использовать файл pi_omp.c.

    Замечание. Возможен запуск гибридных MPI/OpenMP приложений с помощью опции --ntasks-per-node=<ntasks>, например,
        sbatch -N 2 --cpus-per-task=12 --ntasks-per-node=1 my_bat_i

    (подробнее см. man sbatch).


    Приложения для GPU с PGI Accelerator и OpenACC (Компиляция Запуск)

    Компиляторы PGI (pgcc/pgCC/pgf77/pgfortran) позволяют создавать приложения для запуска на GPU (см. [1-3]). Поддержка стандарта OpenACC [4] добавлена в 2012 году с версии 12.6 (см. [5]; в частности, о переходе на OpenACC в [6]).
    Приложения могут быть запущены на узлах с графическими ускорителями кластера "Уран" (umt).

    Настроиться на компиляторы PGI можно с помощью команды mpiset
    (на текущую рабочую версию 11.1)
        mpiset 7

    или, загрузив модуль с нужной версией, с помощью команды module. Например, в начале сеанса
        module switch mpi/default mvapich2/pgi_12.10


    Для компиляции можно использовать команды pgcc или mpicc (см. О компиляторах), например,
        mpicc -o exam_pgi exam.c -ta=nvidia -Minfo=accel -fast

    где опция -ta=nvidia подключает компиляцию на GPU,
    а необязательная опция -Minfo=accel служит для выдачи дополнительной информации о генерации кода для GPU (accelerator kernel).
    Для версий компилятора с поддержкой OpenACC можно вместо опции -ta=nvidia использовать опцию -acc.

    Опция -ta=nvidia,time (где time - подопция) используется для выдачи времени, потраченного на инициализацию GPU (init), перемещение данных (data) и вычисления на GPU (kernels).

    Использование же -ta=nvidia,host задаст генерацию единого кода для host (CPU) и GPU: при наличии GPU программа будет выполняться на GPU, иначе на host.
    Например, mpicc -o exam_gh exam.c -ta=nvidia,host -Minfo .

    Можно узнать, выполняется ли программа на GPU, если установить переменную окружения ACC_NOTIFY в 1
        export ACC_NOTIFY=1

    и запустить программу. При каждом вызове функции GPU (kernel) будет выдаваться сообщение вида
        launch kernel file=...

    что полезно при разработке и отладке программы.

    Примеры C и Fortran программ есть на umt в каталоге
    /opt/pgi/linux86-64/11.1/EXAMPLES/accelerator

    и рассматриваются в [2].
    Замечания.
    1. Помните, что в С, по умолчанию, все константы с плавающей точкой имеют тип double. Поэтому в [2, First Program] для вычислений с одинарной точностью используется 2.0f вместо 2.0.
    2. Для безопасного распараллеливания в С программах (см. [2]) объявления указателей, ссылающихся на распределенную с помощью malloc() память, содержат квалификатор restrict. Такие указатели ссылаются на непересекающиеся области памяти.

    Запуск приложения на счет с использованием GPU можно осуществить с помощью команды
        srun --gres=gpu:1 exam_pgi

    Для задач с большими массивами (> 3 ГБ) следует использовать опцию -C bigmem, которая обеспечит выделение узла с видеокартами Tesla M2090 с памятью Global Memory 6 ГБ (о типах узлов см. Кластер "Уран"). Например,
        srun --gres=gpu:1 -C bigmem exam_pgi

    Возможно совместное использование OpenMP и GPU.

    Общие замечания.
    1. Использование GPU может дать значительное ускорение для задач, где активно задействованы стандартные математические функции (sin, cos, …, см. [1]). При этом надо иметь в виду, что точность вычислений на GPU не та же самая, что на хосте (в частности, и для тригонометрических функций).
      Рекомендуется (см., например, [2, 3]):
    2. До первого запуска kernel осуществлять начальную инициализацию GPU с помощью вызова функции acc_init(acc_device_nvidia).
    3. Копировать массивы целиком (память host <---> память GPU).
    Компилятор стремится минимизировать движение (перемещение) данных, посылая самые маленькие части массивов в обоих направлениях (например, внутренние части прямоугольной матрицы). Более эффективно посылать один большой непрерывный кусок.
    4. Если посчитанные GPU данные не используются в дальнейшем на host, то следует явно указать компилятору, что соответствующие переменные не надо передавать обратно.
    Компилятор обычно возвращает на host все модифицированные данные.
    5. Постараться избавиться от диагностики вида ‘Non-stride-1 accesses for array 'X'’, изменив или структуру массива, или порядок заголовков циклов, или параметры преобразования циклов (loop schedule). Эта диагностика означает, что для соответствующего массива не обеспечен непрерывный доступ к данным и может возникнуть задержка при выполнении групп нитей (threads in groups), которые NVIDIA называет warps. Упрощённо можно думать, что warp выполняется в SIMD или векторном виде с доступом к памяти порциями определённого размера.

    Информацию о технических характеристиках GPU выдает программа pgaccelinfo (см., например, в [2, Setting Up] ; среда PGI предполагается установленной)
        srun --gres=gpu:1 pgaccelinfo

    Опция вида -w 'tesla16' позволяет выдать эту информацию для конкретного (в данном случае 16) узла
         srun -w 'tesla16' --gres=gpu:1 pgaccelinfo


    Ссылки на документацию
    1. GPU Programming with the PGI Accelerator Programming Model by Michael Wolfe / PGI GPU Programming Tutorial. Mar 2011
    2. The PGI Accelerator Programming Model on NVIDIA GPUs. Part 1 by Michael Wolfe / June 2009
    3. The PGI Accelerator Programming Model on NVIDIA GPUs. Part 2 Performance Tuning by Michael Wolfe / August 2009
    4. The OpenACC™ Application Programming Interface. Version 1.0. November, 2011
    5. PGI Accelerator Compilers with OpenACC Directives
    6. PGI Accelerator Compilers with OpenACC by Michael Wolfe / March 2012, revised in August 2012

    Использование системы Matlab для параллельных вычислений

    ИММ УрО РАН предоставляет пользователям системы Matlab (Матлаб) возможность организации параллельных вычислений на кластере
    "Уран" (umt), расширенного узлами с GPU Tesla.
    Подробная информация представлена в полной инструкции "Параллельный Matlab".
    Число лицензий для вычислений на кластере в настоящее время равно 1000.
    Для запуска программ пользователю необходимо установить на своем компьютере программу PuTTY и какой-нибудь X-сервер.

    Параллельные вычисления на кластере инициируются
    1) запуском параллельных програм;
    2) запуском частично параллельных программ (c parfor или spmd);
    3) запуском программ с использованием GPU.

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

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

    Запуск программы на счет осуществляется
    или из командной строки с помощью команд:
    mlrun - для параллельных программ, например,
        mlrun -np 8 -maxtime 20 my_parfunction

    где 8 - число копий функции my_parfunction, 20 - максимальное время счета в минутах;

    mlprun - для частично параллельных программ (с parfor или spmd), например,
        mlprun -np 8 -maxtime 20 my_poolfunction

    где один процесс будет выполнять программу-функцию, а оставшиеся 7 будут использованы в качестве пула для выполнения parfor и spmd;

    mlgrun - для программ с использованием GPU, например,
        mlgrun -np 8 -maxtime 20 my_gpufunction

    где 8 - число процессов (копий функции), каждый из которых может использовать свое GPU.

    или в окне системы Matlab с помощью соответствующих служебных функций:
    imm_sch - для параллельных программ, например,
        job1 = imm_sch(8,20,@my_parfunction);

    imm_sch_pool - для частично параллельных программ (с parfor или spmd), например,
        job2 = imm_sch_pool(8,20,@my_poolfunction);

    imm_sch_gpu - для программ с использованием GPU, например,
        job3 = imm_sch_gpu(8,20,@my_gpufunction);

    В приведенных командах запускаются функции без параметров с использованием 8 процессов, 20 минут - максимальное время счета;
    job1, job2, job3 - ссылки на созданные системой Matlab объекты Job (работа). Имя функции можно набрать с символом "@" или в кавычках.

    Пример. Для функции с параметрами, например rand, вызываемой для генерации 2х3 матрицы случайных чисел с числом процессов 4 и максимальным временем счета 5 минут, следует соответственно набрать в командной строке
        mlrun -np 4 -maxtime 5 rand '1,{2,3}'

    или в окне Matlab
        job = imm_sch(4,5,@rand,1,{2,3});

    Подробнее в Параллельный Matlab/Запуск параллельной программы/Развернутый пример запуска.

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

    Пользователь может контролировать прохождение своей программы через систему запуска как в окне системы Matlab (с версии R2011b) с помощью Job Monitor (см. пункт меню Parallel), так и из командной строки с помощью команд системы запуска.

    Параллельный Matlab

    Общая информация

    Система Matlab (Matrix Laboratory) - разработка компании The MathWorks, предназначенная для выполнения математических расчетов при решении научных и инженерных задач.
    Достоинства Matlab – это, прежде всего, простота матричных операций и наличие многочисленных пакетов программ (Toolbox-ов), среди которых
    Parallel Computing Toolbox, расширяющий Matlab на уровне языка операциями параллельного программирования.
    Parallel Computing Toolbox достаточно для написания и запуска параллельной Matlab программы на локальной машине (Product Documentation).
    Вычисления с Matlab на кластере требуют уже 2 продукта:
        Parallel Computing Toolbox и
        Matlab Distributed Computing Server

    В ИММ имеются все 3 основных продукта для параллельных вычислений с Matlab на кластере (версия Matlab R2011b и старше):
    1) Matlab: 10 лицензий,
    2) Parallel Computing Toolbox: 10 лицензий
        (прежнее название Distributed Computing Toolbox),
    3) Matlab Distributed Computing Server: 1000 лицензий
        (прежнее название Matlab Distributed Computing Engine);
    а также большое количество специализированных Toolbox-ов: по 10 лицензий на SIMULINK, Signal_Blocks, Image_Acquisition_Toolbox, Image_Toolbox, MAP_Toolbox, Neural_Network_Toolbox, Optimization_Toolbox, PDE_Toolbox, Signal_Toolbox, Statistics_Toolbox, Wavelet_Toolbox и 2 лицензии на Filter_Design_Toolbox.

    Параллельный Matlab установлен на кластере "Уран" (umt), расширенного узлами с GPU Tesla.

    Список всех установленных на кластере продуктов Matlab и количество доступных лицензий на них можно уточнить командой
        /opt/matlab-R2010a/etc/lmstat -a

    Название текущей рабочей версии Matlab можно узнать, набрав, например, в командной строке
        echo 'exit' | matlab -nodisplay

    или в окне Matlab
        ver

    Замечания.
    1. При работе в Matlab следует ориентироваться на документацию используемой версии.
    2. Для смены текущей версии следует использовать команду module.

    Пользователь может запускать программы из командной строки или из системы Matlab.
    Для запуска программ из командной строки пользователю необходимо установить на своем компьютере программу PuTTY.
    Запуск параллельных Matlab-программ из командной строки осуществляется с помощью разновидностей команды mlrun.

    Matlab можно запустить в диалоговом окне (основной вид запуска) или в интерактивном текстовом режиме, набрав
        matlab -nodisplay

    Для работы в диалогом окне Matlab на рабочем компьютере пользователя предварительно должен быть установлен и запущен какой-нибудь X-сервер (X2Go, MobaXterm). Заметим, что NX Client (NX клиент для Windows) больше не поддерживается производителем и не доступен для скачивания и установки. Рекомендуется использовать его аналог с открытым кодом X2Go.
    Из командной строки вызвать Matlab
        matlab      
    или
        matlab &    
    (с освобождением командной строки)
    и дождаться появления оконного интерфейса Matlab.
    Запуск параллельных программ из системы Matlab осуществляется с помощью разновидностей служебной функции imm_sch.

    Параллельные вычисления на кластере инициируются
    1) запуском параллельных програм;
    2) запуском частично параллельных программ (c parfor или spmd);
    3) запуском программ с использованием GPU.

    Использование русских букв в Linux версии Matlab

    Для работы с русскими буквами в Matlab'е необходимо правильно настроить кодировку файла с программой, и, при необходимости, настроить ввод русских букв в клиентской программе.

    Возможны два варианта настройки кодировки файла с программой:

    1. Если в основном вы работаете в Windows, то рекомендуется использование кодировки CP1251.
    2. Если вы создаёте, редактируете и запускаете программы в основном в Linux, то рекомендуется использование кодировки UTF-8 (кодировка на кластере по умолчанию).

    Вариант 1
    На кластере "Уран" при запуске Matlab'а можно включить Windows-кодировку CP1251. Для этого необходимо запускать Matlab в окне терминала следующей командой:

    LANG=ru_RU.CP1251 matlab

    После этого можно нормально работать с файлами, подготовленными в Windows.

    Внимание. Данный вариант может не сработать при запуске счётной задачи на узлах кластера.
    Как минимум, в начало счетной программы надо вставить команду:

    feature('DefaultCharacterSet', 'cp-1251');

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

    Если в программе для вывода результатов используется функция disp(), выполняются операции сравнения или сортировки строк с русскими буквами, то стоит попробовать второй вариант.

    Вариант 2
    После передачи файла из Windows на кластер можно перекодировать его в кодировку UTF-8. Следует помнить, что перекодированный файл будет некорректно отображаться в Windows, зато он без проблем будет обрабатываться на кластере.

    2.a Перекодирование файла на кластере в командной строке. Файл перекодируется с помощью команды
    iconv -c -f WINDOWS-1251 -t UTF-8 winfile.m > unixfile.m
    где winfile.m - имя исходного файла, а unixfile.m - перекодированного (подставьте вместо winfile.m и unixfile.m имена ваших файлов, главное, помните - они должны быть различными). Затем можно открыть новый файл в Matlab'е.

    2.b Перекодирование файла на кластере в текстовом редакторе. Для перекодирования файла необходимо запустить текстовый редактор KWrite (Linux'овская кнопка "Пуск", затем ввести в строке поиска имя редактора). При открытии файла с программой указать кодировку cp1251, убедиться, что русские буквы читаются правильно, затем выбрать пункт меню "Файл ->Сохранить как" и указать при сохранении кодировку UTF-8.

    Если есть необходимость перекодировать файлы, полученные с кластера, то это также можно сделать с помощью KWrite. При открытии файла надо выбрать кодировку UTF-8, а потом сохранить файл в кодировке cp1251.

    В командной строке перекодирование из Linux в Windows выглядит так:
    iconv -c -f UTF-8 -t WINDOWS-1251 unixfile.m > winfile.m

    Примечание для администраторов
    В дистрибутиве RHEL и его производных (CentOS, Scientific Linux) отсутствует файл локализации ru_RU.CP1251. Поэтому "Вариант 1" не сработает (Matlab не запустится с сообщением о невозможности установить указанный язык).
    Для генерации файла с кодировкой администратор должен выполнить в Linux'е команду:

    localedef -i ru_RU -f CP1251 ru_RU.CP1251

    Историческое примечание
    Старые версии Matlab'а (до 2010 года) умели работать с единственной кодировкой русских букв ISO-8859-5. Для того, чтобы ее настроить на серверной стороне, необходимо установить переменную окружения LANG в значение ru_RU.8859-5 .
    1) Для корректной обработки русских букв на вычислительных узлах
    в файл ".bashrc" из домашнего каталога пользователя (~/.bashrc) необходимо вставить следующую строку:
        export LANG=ru_RU

    2) в настройках сессии программы PuTTY, в разделе Translation, установить кодировку ISO-8859-5:1999 (Latin/Cyrillic) и сохранить эту сессию для работы с системой Matlab в дальнейшем.

    Запуск параллельной программы

    Основные сведения

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

    Программа пользователя должна быть оформлена как функция (не скрипт) и находиться в начале запускаемого файла, т.е. предшествовать возможным другим вспомогательным функциям. Имя файла должно совпадать с именем первой (основной) функции в файле. Одноименная с файлом функция, не являющаяся первой, никогда не будет выполнена, так как независимо от имени всегда выполняется первая функция файла. Файл должен иметь расширение "m" (Пример параллельной программы).

    Для выполнения программы пользователя всегда вызывается программа MatLab.

    При запуске программы пользователя на кластере в программе MatLab создаётся объект Job (работа) с описанием параллельной работы, которое включает определение объекта Task (задача), непосредственно связанного с заданной программой. Можно сказать, что копия работающей программы представлена в системе MatLab объектом Task.

    Каждый объект Job получает идентификатор (ID) в системе MatLab, равный порядковому номеру. Нумерация начинается с 1.
    Соответствующее имя работы вида Job1, выдаваемое при запуске, хранится в переменной окружения MDCE_JOB_LOCATION и может быть использовано в программе, а сам объект доступен пользователю во время сеанса MatLab.
    Аналогично пользователь имеет доступ и к объектам Task (задача), которые также нумеруются с 1. Идентификатор или номер задачи (1,2,...) - это номер соответствующего параллельного процесса (lab) и его можно узнать с помощью функции labindex, а общее число запущенных копий с помощью функции numlabs.

    Имена работы (Job1), задач (Task1, Task2,…) используются в процессе вычислений для формирования имен файлов и каталогов, связанных с заданной программой. В частности, каталог вида Job1 содержит наборы файлов с информацией по задачам. Имена этих файлов начинаются соответственно с Task1, Task2, …, например, файлы вывода имеют вид Task1.out.mat, Task2.out.mat, …

    Информация о состоянии (State) работы доступна пользователю через соответствующий объект Job.

    Программа пользователя, оформленная в виде объекта Job, поступает в распоряжение системы запуска, которая ставит её в очередь на счет с присвоением своего уникального идентификатора.

    Система запуска создает каталог вида my_function.1 , в котором пользователю интересен, в частности, файл errors (см. Возможные ошибки).

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

    Пользователь может контролировать прохождение своей программы через систему запуска как в окне системы Matlab (с версии R2011b) с помощью Job Monitor (п. меню Parallel/Monitor Jobs), так и из командной строки с помощью команд системы запуска (запросить информацию об очереди, удалить стоящую в очереди или уже выполняющуюся программу).

    Действия пользователя

    Войти на кластер (с помощью PuTTY или MobaXterm) и запустить программу-функцию из командной строки или в окне системы Matlab, указав необходимое для счета число параллельных процессов и максимальное время выполнения в минутах.
    В ответ пользователь должен получить сообщение вида:
    Job output will be written to: /home/u1303/Job1.mpiexec.out
    ,
    где Job1 - имя сформированной работы, 1 - идентификатор работы
    (/home/u1303 - домашний (личный) каталог пользователя).
    Замечание. Для локализации результатов вычислений рекомендуется осуществлять запуск программы (даже в случае запуска встроенных функций Matlab ) из каталога, специально созданного для данной программы в домашнем каталоге.

    Запуск параллельной программы из командной строки
    Команда запуска mlrun имеет вид
        mlrun -np <number_of_procs> -maxtime <mins> <func> ['<args>']

    где
    <number_of_procs> - число параллельных процессов (копий программы)
    <mins> - максимальное время счета в минутах
    <func> - имя файла с одноименной функцией (например, my_function)
    <args> - аргументы функции (не обязательный параметр) берутся в кавычки и представляются в виде
            k,{arg1,...,argn}

    где    k - число выходных аргументов функции, а в фигурных скобках список ее входных аргументов.

    Запуск параллельной программы в окне Matlab
    В командном окне Matlab (Command Window) вызвать служебную функцию imm_sch (в ранних версиях imm_sch_f), которой в качестве параметров передать число процессов, время выполнения и предназначенную для параллельных вычислений функцию с аргументами или без, сохраняя или не сохраняя в переменной (например, job) ссылку на созданный объект Job (имя функции набирается с символом "@" или в кавычках):
        job = imm_sch(np,maxtime,@my_function,k,{arg1,...,argn});

    или
        imm_sch(np,maxtime,'my_function',k,{arg1,...,argn});

    Вид команд запуска mlrun и imm_sch с использованием функции rand см. в пункте Развернутый пример запуска.

    Общее замечание.
    При отсутствии аргументов у функции, что соответствует "0,{}", их можно опустить, например,
    для файла my_function.m с одноименной функцией без параметров запуск имеет вид
    из командной строки
        mlrun -np 8 -maxtime 20 my_function

    в окне Matlab
        job = imm_sch(8,20,@my_function);

    где 8 - число процессов, 20 - максимальное время счета в минутах.

    Доступ к объекту Job (работа)
    Все работы хранятся на кластере. При необходимости доступа к работе, на которую в текущий момент отсутствует ссылка, можно (1) в окне Job Monitor правой кнопкой мыши выделить нужную работу и выбрать соответствующую опцию в контекстном меню (Assign Job to Workspace в версии R2012a, по умолчанию рабочей) или (2) по идентификатору (ID) определить ссылку на работу (обозначаемую job) с помощью, например, команд:
        c = parallel.cluster.Generic
        job = c.findJob('ID',1)

    Примечание.
    Вышеприведенные команды предназначены для версий MatLab с профилем кластера, т.е. начиная с R2012a.
    В ранних версиях (с конфигурацией кластера) следует набирать:
        s = findResource('scheduler', 'type', 'generic')
        job = findJob(s,'ID',1)

    При этом в поле DataLocation структуры s должен быть текущий каталог (тот, в котором ищем работу). Если каталог другой, то можно выполнить
        clear all
        и повторить предыдущие команды.

    Состояние работы
    Состояние работы можно посмотреть в поле State работы job, набрав
        job    
    или    job.State
    или узнать с помощью Job Monitor.
    Основные значения состояния работы следующие:
        pending      (ждет постановки в очередь)
        queued       (стоит в очереди)
        running      (выполняется)
        finished     (закончилась)

    Окончания счета (состояние finished) можно ждать с помощью функции wait
        wait(job);    
    или    job.wait()

    Вывод результатов

    В окне Matlab (с R2012a) для работы job и любой ее задачи (Task) с номером n=1,2,... можно выдать (далее для удобства n=1)
    1) протокол сеанса:
        job.Tasks(1).Diary

    2) информацию об ошибках (поле ErrorMessage)
        job.Tasks(1)    
    или    job.Tasks(1).ErrorMessage
    3) результаты (значения выходных параметров) работы job в целом (по всем Task-ам):
        out = job.fetchOutputs

    Тогда значение 1-го выходного параметра 1-ой задачи (Task)
        res = out{1,1}

    или, если он единственный, то он опускается,
        res = out{1}

    соответственно, значение 2-го выходного параметра 1-ой задачи (Task)
        res2 = out{1,2}

    Другой способ выдачи результатов по задачам
        out1 = job.Tasks(1).OutputArguments

    Замечания.
    1. Эту же информацию можно выдать, запустив Matlab в интерактивном текстовом режиме (matlab -nodisplay) и набирая затем упомянутые команды.
    2. Если ссылка на работу (job) отсутствует, то ее можно найти по идентификатору.
    3. Для ранних версий (до R2012a) следует использовать следующие команды, чтобы выдать
       1) протокол сеанса:
        job.Tasks(1).CommandWindowOutput

       3) результаты (значения выходных параметров) работы job в целом (по всем Task-ам):
        out = job.getAllOutputArguments

    Вывод из файлов
    По завершении параллельной работы в файлы вывода TaskN.out.mat ее задач (номер задачи N=1,2,…np; np - число задач данной работы) попадают
    - выходные параметры функции пользователя (массив ячеек argsout),
    - содержимое stdout (переменная commandwindowoutput) и
    - содержимое stderr (переменная errormessage).

    Выдать эту информацию можно из командной строки или в окне системы Matlab.

    Приведем примеры соответствующих команд для Task1 работы с именем Job1.
    Предполагаем, что команды выполняются в каталоге, из которого была запущена программа.
    Вывод из командной строки
    первого выходного параметра:
        echo 'load Job1/Task1.out.mat; argsout{1}, exit' | matlab -nodisplay

    содержимого stdout:
        echo 'load Job1/Task1.out.mat; commandwindowoutput, exit' | matlab -nodisplay

    содержимого stderr (ошибок трансляции):
        echo 'load Job1/Task1.out.mat; errormessage, exit' | matlab -nodisplay

    Вывод в окне системы Matlab
    После вызова, например,
        matlab &

    набрать команду
        load Job1/Task1.out.mat

    и выдать
    первый выходной параметр:
        argsout{1}

    содержимое stdout:
        commandwindowoutput

    содержимое stderr (ошибки трансляции):
        errormessage

    Если в окне системы Matlab открыто окно Workspace, то интересующие пользователя переменные будут видны в нем, и можно выдавать только те из них, которые не пусты.

    Перед просмотром файла вывода следующей задачи, т.е. перед загрузкой в Matlab, например, файла Job1/Task2.out.mat, рекомендуется очищать окно Workspace командой
        clear


    Развернутый пример запуска

    В качестве примера запуска программы на кластере используем функцию rand, вызываемую для генерации 2х3 матрицы случайных чисел
    (традиционный вызов функции: y = rand(2,3)).
    Для получения 4 экземпляров матрицы задаем число процессов, равное 4. Максимальное время счета пусть будет равно 5 минутам.

    Запускать функцию будем на кластере "Уран" (umt) (см. Вычислительные ресурсы), для удобства в каталоге test, специально созданном заранее в домашнем каталоге пользователя /home/u9999, где u9999 – login пользователя (см. Схема работы на кластере и Базовые команды ОС UNIX).

    Для запуска функции rand из командной строки используется команда mlrun,
    а из системы Matlab - служебная функция imm_sch (см. Параллельный Matlab/Общая информация).

    Войдя на umt через PuTTY, для запуска rand можно
    1) выполнить команду
        mlrun -np 4 -maxtime 5 rand '1,{2,3}'

    или
    2) вызвать Matlab в интерактивном текстовом режиме командой
        matlab -nodisplay

    и в ответ на приглашение (>>) набрать
        job = imm_sch(4,5,@rand,1,{2,3});

    где job – ссылка на сформированную работу.
    Для выхода из Matlab следует набрать
        exit
       или   quit

    Для запуска программ из окна Matlab пусть установлен MobаXterm.
    Тогда войдя на umt из MobаXterm, можно вызвать Matlab командой
        matlab &

    и в открывшемся окне набрать
        job = imm_sch(4,5,@rand,1,{2,3});

    После выполнения команды mlrun или служебной функции imm_sch выдается строка вида
    Job output will be written to: /home/u9999/test/Job1.mpiexec.out

    где Job1 - имя сформированной работы, 1 - идентификатор (номер) работы.

    Если ресурсов кластера достаточно, задача войдет в решение. (см. Запуск задач на кластере в системе SLURM)

    Дожидаемся окончания задачи, т.е. job.State должно быть finished.
    В окне Matlab контролировать состояние задачи можно и с помощью Job Monitor (п. меню Parallel/Monitor Jobs).

    Результаты выдаем с помощью команд:
    со всех процессов
        out = job.fetchOutputs

    а для выдачи матрицы, полученной 1-ым процессом (т.е. Task1)
        out{1}

    и т.д.

    Для выдачи результатов ранее посчитанной работы, на которую в текущий момент нет ссылки, следует обеспечить к ней доступ, например используя Job Monitor.

    Некоторые рекомендации

    1. Начать работу на кластере рекомендуется с запуска своей последовательной программы в тестовом однопроцессном варианте, например,
        mlrun -np 1 -maxtime 20 my_function

    где my_function – функция без параметров, максимальное время счета 20 минут.
    2. После преобразования последовательной программы в параллельную её работоспособность можно проверить, выполняя шаги, приведенные в пункте Как убедиться в работоспособности программы при рассмотрении примеров с распределенными массивами.

    Запуск частично параллельной программы (c parfor или spmd)

    Введение

    Частично параллельной будем называть программу, при выполнении которой наряду с последовательными возникают параллельные вычисления, инициируемые параллельными конструкциями языка Matlab parfor и spmd.

    Использование параллельного цикла parfor или параллельного блока spmd предполагает предварительное открытие Matlab пула, т.е. выделение необходимого числа процессов (Matlab workers или labs), на локальной машине или на кластере.

    Запуск частично параллельных программ с открытием Matlab пула на кластере можно выполнять
    (1) по аналогии с запуском параллельных программ из командной строки или в окне системы Matlab (запуск с неявным заданием пула) или
    (2) на основе профиля кластера (с версии R2012a, ранее параллельной конфигурации) при работе в окне системы Matlab (запуск с явным заданием пула).

    Пользователь может контролировать прохождение своей программы через систему запуска как в окне системы Matlab (с версии R2011b) с помощью Job Monitor (см. пункт меню Parallel), так и из командной строки с помощью команд системы запуска.

    1. Запуск частично параллельной программы с неявным заданием пула

    При запуске из командной строки вместо команды mlrun (для параллельных программ) следует использовать команду mlprun, например,
        mlprun -np 12 -maxtime 20 my_function '1, {x1, x2}'

    а при запуске в окне вместо функции imm_sch использовать функцию imm_sch_pool, например,
        job = imm_sch_pool(12,20,@my_function,1,{x1,x2});

    для функции, определенной как
        function y = my_function(x1,x2)

    и запущенной на 12 процессах с максимальным временем счета 20 минут.

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

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

    2. Запуск частично параллельной программы с явным заданием пула
    на основе профиля кластера

    Явное задание пула возможно при работе в окне Matlab с помощью команды matlabpool (см. help matlabpool). Число выделенных процессов и время, в течение которого они будут доступны пользователю, зависят от заданного профиля кластера (см. пункт меню Help/Product Help/Parallel Computing Toolbox/User's Guide/Programming Overview/Cluster Profiles).
    Команда
        matlabpool

    без параметров открывает пул, используя профиль по умолчанию с указанным в нем размером пула. В ИММ УрО РАН по умолчанию Matlab пул открывается на узлах кластера (тип кластера Generic), поскольку управляющий компьютер, выступающий в роли локальной машины (Matlab client), не должен использоваться для длительных вычислений.
    Пользователь может выбрать профиль по умолчанию из уже существующих профилей или создать новый, используя пункт меню Parallel окна Matlab.

    Команда matlabpool с указанием размера пула, например
        matlabpool open 28

    открывает пул, переопределяя размер, заданный по умолчанию. При этом следует иметь в виду, что существует ограничение на максимальное число доступных пользователю процессов на кластере.
    В результате открытия пула сформированная для кластера работа с именем вида JobN (где N=1,2,...) поступает в распоряжение системы запуска и ставится в очередь на счет. Если свободных процессов достаточно, то пул будет открыт на время, заданное в профиле по умолчанию, с выдачей сообщения вида:
    Starting matlabpool using the 'imm_20mins' profile ... Job output will be written to: /home/u1303/my_directory/Job1.mpiexec.out
    connected to 28 labs.

    Размер пула можно узнать, набрав
        matlabpool size

    По завершение вычислений, связанных с пулом, его следует закрыть
        matlabpool close

    Внимание. Пул закрывается по истечении времени с диагностикой вида:
    The client lost connection to lab 12.
    This might be due to network problems, or the interactive matlabpool job might have errored.

    Запуск частично параллельной программы на Matlab клиенте
    (не разрешается для длительных вычислений)
    Итак, схема использования параллельных конструкций parfor и spmd в окне Matlab такова:
        matlabpool
         ...
        % вычисления с использованием parfor или spmd,
        % выполняемые построчно или
        % собранные в программу (частично параллельную)
        % и запущенные из файла
         ...
        matlabpool close

    При этом все вычисления, кроме параллельных, выполняет Matlab client (см., например, Introduction to Parallel Solutions/Interactively Run a Loop in Parallel.)

    Запуск частично параллельной программы с помощью команды batch
    В системе Matlab существует команда (функция) batch, которая позволяет запускать программы в пакетном режиме, разгружая Matlab client (см., например, Introduction to Parallel Solutions/Run a Batch Job). Эта команда выполняется асинхронно, т.е. интерактивная работа пользователя не блокируется.
    Где будет выполняться программа и максимально сколько времени, определяется планировщиком (scheduler), заданным в профиле кластера по умолчанию: в ИММ на кластере, тип планировщика generic. Для выполнения программы создается объект Job (работа). Команда batch вида
        job = batch('my_mfile')

    (job - ссылка на объект работа)
    запускает программу (скрипт или функцию) my_mfile в однопроцессном варианте. В ответ на команду batch выдается сообщение вида
    Job output will be written to: /home/u1303/my_directory/Job1.mpiexec.out

    содержащее идентификатор работы (ID), равный здесь 1. Сформированная для кластера работа ставится в очередь и при наличии свободных процессов входит в решение с именем очереди вида my_mfile.1.

    Для запуска на кластере частично параллельной программы можно использовать команду batch с открытием пула. При этом выделяемое на кластере число процессов будет на 1 больше заданного размера пула.
    Так, например, для выполнения команды
        job = batch('my_mfile','matlabpool',11)

    потребуется 12 процессов: 1 для программы my_mfile, 11 для пула (см., например, Introduction to Parallel Solutions/Run a Batch Parallel Loop). Время счета здесь определяется временем, заданным в профиле по умолчанию (в аналогичной команде imm_sch_pool все аргументы задаются явно).

    Вывод результатов

    По завершении работы job можно выдать
    1) протокол сеанса
        job.diary

    2) результаты работы
        out=job.fetchOutputs
        celldisp(out)

    (fetchOutputs вместо getAllOutputArguments в ранних версиях, использовавших конфигурацию кластера, а не профиль)
    3) информацию об ошибках (поле ErrorMessage)
        job.Tasks(1)

    или
        job.Tasks(1).ErrorMessage

    Запуск программ с использованием GPU

    Программа с использованием GPU - это параллельная программа, каждая ветвь (копия, процесс), которой может использовать своё GPU.
    Поэтому к программе с GPU применимо почти все, что относится к параллельной программе (в частности, это должна быть программа-функция). Особенности запуска программ с GPU отмечены ниже.

    Программа с использованием GPU в результате запуска ставится в очередь на счет в системе SLURM. Пользователь может контролировать прохождение своей программы через эту систему с помощью соответствующих команд или в окне системы Matlab (с версии R2011b) с помощью Job Monitor (см. пункт меню Parallel).

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

    Запуск программы на счет осуществляется по аналогии с запуском параллельных программ:
    из командной строки с помощью команды mlgrun, например,
        mlgrun -np 8 -maxtime 20 my_gpufunction

    или в окне системы Matlab с помощью служебной функции imm_sch_gpu, например,
        job = imm_sch_gpu(8,20,@my_gpufunction);

    В приведенных командах запускается функция без параметров с использованием 8 процессов, 20 минут - максимальное время счета.
    При этом каждый из 8 процессов (копий функции) может использовать своё GPU.

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

    Возможные ошибки

    1) Если не хватает лицензий для запуска на кластере функции my_function из одноименного файла my_function.m, то информация об ошибке находится в файле my_function.1/errors.
    При этом, как правило, файл my_function.1/output содержит MPIEXEC_CODE=123
    Кто занимает лицензии можно узнать, набрав команду lmstat .
    Внимание.
    В настоящее время система запуска не контролирует число лицензий, доступность лицензий определяется в начале счета.

    2) В ответ на команду load Job1/Task1.out.mat получено сообщение
    ??? Error using ==> load
    Unable to read file Job1/Task1.out.mat: Нет такого файла или каталога.

          Возможно, команда вызвана не из того каталога.

    3) ErrorMessage (или errormessage) содержит ошибки трансляции, например:
    Undefined function or variable 'my_function'.

          Имя или расширение файла, имя функции или переменной
          отсутствует или указано неверно.
          Имя отсутствует, возможно, по причине случайного запуска
          из другого каталога.
    Invalid function name 'j-cod'.

          В именах файлов и функций не должно быть минуса ("-"),
          только подчерк ("_").
    Invalid file identifier. Use fopen to generate a valid file identifier.

          Возможно, имя файла задано русскими буквами.
    Внимание.
    В случае таких ошибок в файле my_function.1/errors обычно содержится строка
    [0]application called MPI_Abort(MPI_COMM_WORLD, 42) - process 0

    Помните:
    имя файла должно совпадать с именем первой функции в файле
    , так как,
    во-первых, при запуске программы ищется файл с именем, указанным в команде запуска,
    и, во-вторых, в нем выполняется, прежде всего, первая функция.
    Если они не совпадают и при запуске указано имя функции (например, my_function), то файл не будет найден и будет выдана ошибка вида:
    Undefined function or variable 'my_function'.

    Если они не совпадают и при запуске указано имя файла (например, my_code), то выполнится первая функция файла независимо от ее имени. При этом наличие одноименной с файлом функции, не являющейся первой, приведет к выдаче в CommandWindowOutput (или commandwindowoutput) предупреждения вида:
    Warning: File: my_code.m Line: 25 Column: 14
    Function with duplicate name "my_code" cannot be called.

    4) Если выполнение программы прервано принудительно, например, по истечению времени, то выходная информация отсутствует (т.е. файлы вывода вида Task1.out.mat будут пусты). При этом состояние работы (поле State объекта работа) будет running, в то время как состояния её задач (поля State для Tasks(n), где n=1,2,...) могут быть как running, так и finished, если часть копий программы успела финишировать до окончания заказанного времени.
    В случае исчерпания времени соответствующая информация попадает в файл my_function.1/errors.

    5) В случае аварийного завершения работы программы в домашнем каталоге пользователя (~) могут оставаться файлы вида mpd.hosts.123456 и mpd.mf
          Их следует периодически удалять вручную.

    Завершение работы

    Работу, в которой нет больше необходимости, следует уничтожить, используя Job Monitor (Delete в контекстном меню) или функцию delete (в ранних версиях destroy), освобождая тем самым ресурсы кластера
        job.delete

    также удалить файл вида Job1.mpiexec.out (предполагаем, что Job1 - имя удаляемой работы),
    а затем почистить Workspace
        clear job

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

    Не все работы заканчиваются с признаком finished. Так, по истечении времени счета работа будет прервана в состоянии running.
    Для уничтожения в текущем каталоге всех или только завершившихся (finished) работ можно воспользоваться написанной в ИММ УрО РАН функцией job_destroy.

    Вызов job_destroy без параметра
    из командной строки:
        echo 'job_destroy, exit' | matlab -nodisplay

    в окне:
        job_destroy

    уничтожает только завершившиеся работы.

    Вызов job_destroy с параметром (тип и значение параметра не существенны)
    из командной строки:
        echo 'job_destroy(1), exit' | matlab -nodisplay
        или
        echo "job_destroy('all'), exit" | matlab -nodisplay

    в окне:
        job_destroy(1)
        или
        job_destroy('all')

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

    После выполнения job_destroy с параметром, например, job_destroy(1), нумерация работ начинается с 1.

    После уничтожения ненужных работ следует удалить на них ссылки в Workspace с помощью команды clear.

    Важные замечания.
    1. Нумерация работ (Job) в каталоге пользователя начнется с 1 в новом сеансе Matlab при отсутствии каталогов и файлов предыдущих работ (Job...).
    2. Каталог вида my_function.1 не удаляется при использовании команды job_destroy. При новых запусках одной и той же программы образуются аналогичные каталоги с возрастающими номерами: my_function.2, my_function.3
    Пользователь должен сам удалять ненужные каталоги.

    Пример параллельной программы

    Пример взят с сайта MathWorks и иллюстрирует основные (базовые) принципы программирования параллельной программы-функции.

    Копия работающей функции, т.е. задача (Task), для которой значение labindex равно 1, создает магический квадрат (magic square) с числом строк и столбцов равным числу выполняющихся копий (numlabs) и рассылает матрицу с помощью labBbroadcast остальным копиям. Каждая копия вычисляет сумму одного столбца матрицы. Все эти суммы столбцов объединяются с помощью функции gplus, чтобы вычислить общую сумму элементов изначального магического квадрата.
        function total_sum = colsum
        if labindex == 1
          % Send magic square to other labs
          A = labBroadcast(1,magic(numlabs))
        else
          % Receive broadcast on other labs
          A = labBroadcast(1)
        end
        % Calculate sum of column identified by labindex for this lab
        column_sum = sum(A(:,labindex))
        % Calculate total sum by combining column sum from all labs
        total_sum = gplus(column_sum)
        end

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

    В прикрепленном файле ml_session.PNG (см. ниже) демонстрируется запуск функции colsum в окне системы Matlab с использованием 4-х вычислительных процессов и максимальным временем счета 1 минута.

    Функция хранится как файл colsum.m в каталоге ng5 пользователя (полный путь: /home/u1303/ng5).
    После запуска функции colsum с помощью служебной функции imm_sch_f, например
        job = imm_sch_f(4,1,'colsum',1,{});

    или
        job = imm_sch(4,1,@colsum,1);

    выдается сообщение:
    Job output will be written to: /home/u1303/ng5/Job1.mpiexec.out
    ,
    в котором указано имя сформированной работы Job1.
    Проверив состояние работы и убедившись, что она закончилась, можно выдать результаты счета.

    Прикрепленный файлРазмер
    Иконка изображения ml_session.PNG73.66 КБ

    Примеры с распределенными массивами

    Введение

    Распределение данных по процессам предназначено для ускорения счета и экономии памяти.
    Параллельные вычисления с использованием распределенных массивов подробно описаны на сайте Matlab, в частности, в подразделе Working with Codistributed Arrays.

    Распределенный массив состоит из сегментов (частей), каждый из которых размещен в рабочей области (workspace) соответствующего процесса (lab). При необходимости информацию о точном разбиении массива можно запросить с помощью функции getCodistributor (подробнее см. Obtaining information About the Array). Для просмотра реальных данных в локальном сегменте распределенного массива следует использовать функцию getLocalPart.

    Возможен доступ к любому сегменту распределенного массива.
    Доступ к локальному сегменту будет быстрее, чем к удаленному, поскольку последний требует посылки (функция labSend) и получения (функция labReceive) данных между процессами.
    Содержимое распределенного массива можно собрать с помощью функции gather в один локальный массив, продублировав его на всех процессах или разместив только на одном процессе.

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

    Существует 3 способа создания распределенного массива (см. Creating a Codistributed Array):
    1) деление исходного массива на части,
    2) построение из локальных частей (меньших массивов),
    3) использование встроенных функций Matlab (типа rand, zeros, ...).

    1) Деление массива на части может быть реализовано с помощью функции codistributed (Пример 1). При этом в рабочей области каждого процесса расположены исходный массив в своем полном объеме и соответствующий сегмент распределенного массива. Таким образом, этот способ хорош при наличии достаточного места в памяти для хранения тиражируемого (replicated) исходного массива.
    Размерности исходного и распределенного массивов совпадают.

    Деление массива может быть произведено по любому из его измерений.
    По умолчанию в случае двумерного массива проводится горизонтальное разбиение, т.е. по столбцам, что выглядит естественно с учетом принятого в системе Matlab размещения матриц в памяти по столбцам (как в Фортране).

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

    3) Для встроенных функций Matlab (типа rand, zeros, ...) можно создавать распределенный массив любого размера за один шаг (см. Using MATLAB Constructor Functions).

    Вверх
    Как можно использовать распределенные массивы

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

    Даются возможные схемы решения таких задач с использованием распределенных массивов. Показан переход от исходной последовательной программы к параллельной с распределенными вычислениями. Соответствующие изменения выделены.
    Замечание.
    Хотя дистрибутивные массивы совместимы (в отличие от цикла parfor и GPU) с глобальными переменными, необходимо тщательно следить за тем, чтобы изменения глобальных переменных в процессе обработки одной порции данных не влияли на результаты обработки других порций, тем самым обеспечивая независимость вычислений частей дистрибутивных массивов.
    Там, где допустимо, проще использовать цикл parfor или вычисления на GPU.

    Вверх
    Пример 1. Деление массива на части

    Пусть требуется вычислить значения некоторой функции 10 вещественных переменных. Аргументом функции является 10-мерный вектор.
    Значение функции необходимо вычислить для n точек (значений аргумента), заданных 10хn матрицей. Вычисление матрицы производится по некоторому заданному алгоритму и не требует много времени.

    Обозначения.
    my_func - вычисляемая функция
    М - массив для аргументов функции my_func
    F - массив для значений функции my_func
    M_distr - распределенный массив для M (той же размерности)
    F_distr - распределенный массив для F (той же размерности)

    Исходная программа
    Результирующая программа
    function test_1()
    % инициализация данных
    n=1000;
    ...
    % резервирование памяти
    M = zeros(10,n);
    F = zeros(1,n);
    % заполнение матрицы М
    ...
    function test_1()
    % инициализация данных
    n = 1000;
    ...
    % резервирование памяти
    M = zeros(10,n);
    F = zeros(1,n);
    % заполнение матрицы М
    ...
    % создание распределенных массивов
    % разбиение по умолчанию проводится
    % по столбцам (2-му измерению)
    M_distr = codistributed(M);
    F_distr = codistributed(F);
    % вычисление функции
    for i = 1:n
      F(1,i) = my_func(M(:,i));
    end
    % вычисление функции
    for i = drange(1:size(M_distr,2))
      F_distr(1,i) = my_func(M_distr(:,i));

    end
    % сбор результатов на 1-ом процессе
    F = gather(F_distr,1);
    save ('test_res_1.mat', 'F', 'M'); if labindex == 1
      save ('test_res_1.mat', 'F', 'M');
    end
    return
    end
    return
    end

    Вверх
    Пример 2. Построение массива из частей.
    Распределенный массив как объединение локальных массивов

    Сформировать таблицу значений функции 2-х вещественных переменных ((x,y) --> F) на прямоугольной сетке размера 120x200, заданной векторами (x1:x2:x3 и y1:y2:y3). Существует алгоритм вычисления значения функции в точке , обозначенный my_func.

    Обозначения.
    my_func - вычисляемая функция 2-х переменных
    F - массив для значений функции my_func
    F_loc - локальный массив, который заполняется соответствующими значениями функции на каждом процессе и затем берется за основу (рассматривается как сегмент) при построении распределенного массива F_distr
    F_distr - распределенный массив, содержимое которого собирается в массиве F на 1-ом процессе

    Вариант 1.
    Распараллеливание проводится по внешнему циклу (по x - первому индексу).
    Предполагается, что число строк 120 кратно numlabs - числу процессов, заказанных при запуске программы на счет.

    Исходная программа
    Результирующая программа
    function test_2()
    % инициализация данных,
    % в частности,
    % x1, x2, x3, y1, y2, y3
    ...
    function test_2()
    % инициализация данных,
    % в частности,
    % x1, x2, x3, y1, y2, y3
    ...
    m_x = x1:x2:x3;
    n = 120/numlabs;
    % выделение памяти
    F = zeros(120,200);
    % вычисление функции
    i = 1;
    for x = x1:x2:x3
      ...
    % выделение памяти
    F_loc = zeros(n,200);
    % вычисление функции
    % i = 1;
    for i = 1:n
      k = (labindex-1)*n + i;
      x = m_x(k);

      ...
      j = 1;
      for y = y1:y2:y3
        F(i,j) = my_func(x,y);
        j = j + 1;
      end
      i = i + 1;
    end
      j = 1;
      for y = y1:y2:y3
        F_loc(i,j) = my_func(x,y);
        j = j + 1;
      end
    %   i = i + 1;
    end
    % распараллеливание проведено по строкам
    % (1-му измерению) => codistributor1d(1, ...)
    codist = codistributor1d(1, [], [120 200]);
    F_distr = codistributed.build(F_loc, codist);
    F = gather(F_distr, 1);
    save ('test_res_2.mat', 'F'); if labindex == 1
      save ('test_res_2.mat', 'F');
    end
    return
    end
    return
    end

    Вариант 2.
    Распараллеливание проводится по внутреннему циклу (по y - второму индексу).
    Предполагается, что число столбцов 200 кратно numlabs - числу процессов, заказанных при запуске программы на счет.

    Исходная программа
    Результирующая программа
    function test_2()
    % инициализация данных,
    % в частности,
    % x1, x2, x3, y1, y2, y3
    ...
    function test_2()
    % инициализация данных,
    % в частности,
    % x1, x2, x3, y1, y2, y3
    ...
    m_y = y1:y2:y3;
    n = 200/numlabs;
    % выделение памяти
    F = zeros(120,200);
    % вычисление функции
    i = 1;
    for x = x1:x2:x3
      ...
      j = 1;
      for y = y1:y2:y3
    % выделение памяти
    F_loc = zeros(120,n);
    % вычисление функции
    i = 1;
    for x = x1:x2:x3
      ...
    %   j = 1;
      for j = 1:n
        k = (labindex-1)*n + j;
        y = m_y(k);
        F(i,j) = my_func(x,y);
        j = j + 1;
      end
      i = i + 1;
    end
        F_loc(i,j) = my_func(x,y);
    %     j = j + 1;
      end
      i = i + 1;
    end
    % распараллеливание проведено по столбцам
    % (2-му измерению) => codistributor1d(2, ...)
    codist = codistributor1d(2, [], [120 200]);
    F_distr = codistributed.build(F_loc, codist);
    F = gather(F_distr, 1);
    save ('test_res_2.mat', 'F'); if labindex == 1
      save ('test_res_2.mat', 'F');
    end
    return
    end
    return
    end

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

    Вверх
    Как убедиться в работоспособности программы

    Перед первым запуском программы-функции на кластере ее стоит проверить сначала в однопроцессорном варианте с отладчиком Debug (см.,например, Debug a MATLAB Program), а затем в параллельном режиме pmode. Поскольку политика использования вычислительных ресурсов ИММ УрО РАН не предполагает длительных вычислений на управляющем компьютере, запускать программу в режимах Debug и pmode следует с тестовым набором данных.

    Итак, рекомендуется следующая последовательность выхода на счет:
        Debug
        pmode
        кластер

    Запуск параллельной программы с отладчиком Debug (в однопроцессорном режиме) можно осуществить, например, предварительно открыв текст программы в редакторе (Editor), установив необходимые контрольные точки (щелкая, к примеру, левой клавишей мыши справа от номера нужной строки) и нажав клавишу F5 (см. пункт меню Debug).

    Стартовать режим pmode на 4-х процессах (для наглядности) можно в окне Matlab (Command Window) с помощью команды
        pmode start 4

    Затем в командной строке открывшегося параллельного окна (Parallel Command Window) вызвать свою программу.
    Закрыть параллельный режим можно или из параллельного окна командой
        exit

    или из окна Matlab командой
        pmode exit

    Для контроля за данными полезна функция getLocalPart.

    Запуск на кластере можно осуществить в окне Matlab с помощью функции imm_sch.

    Использование параллельного профилирования

    Основные понятия

    Профилирование предназначено для выявления наиболее затратных по времени мест в программе с целью увеличения ее быстродействия (см. Profile to Improve Performance).
    Профилирование параллельных программ определяет как затраты на вычисление функций, так и затраты на коммуникации (см. Profiling Parallel Code).
    Профилирование в Matlab осуществляется с помощью инструмента, называемого профилировщик или профайлер (profiler).

    Результатом профилирования являются суммарный и детальный отчеты о выполнении программы.
    Суммарный отчет о профилировании параллельной программы содержит для каждого параллельного процесса (lab) информацию о времени вычисления функций и частоте их использования, а также о времени, затраченном на обмены (коммуникации) и ожидание обменов с другими процессами.
    Для проблемных функций полезно выдавать детальный отчет, в котором содержится статистика по строкам функций, а именно: время выполнения и частота использования.

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

    Вверх
    Действия пользователя

    Действия пользователя иллюстрируются на примере функции colsum() в соответствии с примером функции foo() из раздела Examples в описании команды (функции) mpiprofile.

    Внесение изменений в текст программы
    1) В заголовок функции добавить выходной параметр для информации о профилировании, назовем его p:
        function [p, total_sum] = colsum

    2) В тело функции добавить
    команду mpiprofile для включения профилирования (начала сбора данных)
        mpiprofile on
    и при необходимости (или желании) выключения профилирования
         mpiprofile off
    вызов mpiprofile как функции для доступа к сгенерированным данным и сохранение собранной информации в выходном параметре p
         p = mpiprofile('info');
    Скорректированный текст программы может быть, например, таким, как в прикрепленном файле ml_prof_colsum.PNG (см. ниже).

    Запуск программы на профилирование
    1) При запуске функции указать увеличенное соответственно на 1 число выходных параметров.
    2) Запустить программу-функцию из командной строки или в окне Matlab
    запуск из командной строки
        mlrun -np 9 -maxtime 5 colsum '2,{}'

    запуск в окне Matlab
        imm_sch_f(9,5,'colsum',2,{});

    или
        j = imm_sch_f(9,5,'colsum',2,{});

    Просмотр результатов профилирования
    Пусть программа запущена в окне Matlab командой вида
        j = imm_sch_f(...);

    и предполагается, что просмотр результатов профилирования будет осуществлен в том же сеансе. Окончания счета при желании можно ждать с помощью команды
        wait(j);

    При другом запуске или при просмотре результатов профилирования в другом сеансе необходимо по известному пользователю идентификатору закончившейся работы (например, Job8) определить значение j, выполнив следующие действия:
        sched = findResource('scheduler', 'type', 'generic');
        j=findJob(sched, 'id', 8);

    Внимание.
    При необходимости выполнить эти действия для другой функции, находящейся в другом каталоге того же сеанса Matlab, следует набрать команду
        clear all

    Для просмотра результатов профилирования завершившейся программы надо выполнить следующие действия (см. раздел Examples в mpiprofile):
    1) получить результаты:
        results = getAllOutputArguments(j);

    2) выделить вектор с информацией о профилировании:
        p_Vector = [results{:, 1}];

    3) запустить вьюер:
        mpiprofile('viewer', p_Vector);

    Вид окна Matlab после выполнения перечисленных действий приведен в прикрепленном файле ml_prof_session.PNG (см. ниже).

    Замечание.
    Для повторного использования эти переменные можно сохранить, например, в файле results_file.mat :
        save('results_file','results', 'p_Vector')

    и загрузить в другом сеансе:
        load ('results_file')

    Вверх
    Некоторые советы

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

    Профилирование может быть использовано
    - в качестве инструмента отладки;
    - для изучения (понимания) незнакомых файлов.
    При отладке программы детальный отчет даст представление о том, какие строки выполнялись, а какие нет. Эта информация может помочь в расширении набора тестов.
    Для очень длинного файла с незнакомым матлабовским кодом можно использовать профайлер, чтобы посмотреть, как файл в реальности работает, т.е. посмотреть вызываемые строки в детальном отчете.

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

    Прикрепленный файлРазмер
    Иконка изображения ml_prof_colsum.PNG38.44 КБ
    Иконка изображения ml_prof_session.PNG85.25 КБ

    О реализации работы системы Matlab на кластере

    Запуск параллельной программы пользователя на кластере организован в соответствии с рекомендациями разработчиков Matlab в разделах
        Programming Distributed Jobs и
        Programming Parallel Jobs
    с учетом используемого в ИММ планировщика (типа Generic Scheduler в терминологии Matlab).
    Замечание. Ссылки на сайт разработчика Matlab даны на момент подключения системы Matlab (~2010).

    Для осуществления такого запуска необходимо:

    Со стороны системы Matlab
    1) Обеспечить наличие функций Submit и Decode.
    Функция Submit выполняется Matlab клиентом на хосте (управляющей машине) и основное ее назначение - установить необходимые переменные окружения, в том числе для функции Decode, перед обращением к планировщику (Scheduler).
    Функция Decode выполняется автоматически Matlab сервером (worker) на каждом узле и основное ее назначение – забрать переданные планировщиком через переменные окружения значения, которые Matlab worker использует для проведения вычислений на узлах кластера.
    2) Задать последовательность действий для описания параллельной работы (Job, точнее ParallelJob), в рамках которой и будут проводиться программой Matlab вычисления функции пользователя на кластере. Основные действия описаны на сайте Matlab и продемонстрированы, в частности, на примере. В ИММ с учетом пакетной обработки эти действия дополнены перехватом stdout и stderr, т.е. установкой свойства CaptureCommandWindowOutput в значение true для всех задач (Task) программируемой работы (Job) (коротко о Job и Task см. в пункте Основные сведения).
    С целью дальнейшего многократного использования все необходимые для программирования параллельной работы действия оформлены в виде служебной функции imm_sch_f, обозначенной на рисунке ниже как scheme function. Этой функции в качестве параметров передаются число параллельных процессов, время счета, имя и параметры функции пользователя, предназначенной для распараллеливания вычислений.
    Функция imm_sch_f служит для запуска параллельных программ.
    При запуске параллельной программы в окне системы Matlab пользователь явно обращается к этой функции.
    3) Для своевременного удаления информации о завершенных работах предоставить в распоряжение пользователя функцию job_destroy.

    Со стороны планировщика
    1) Обеспечить пользователя командой запуска параллельной программы из командной строки, аналогичной mpirun (заменённой впоследствии на mqrun). Эта команда получила название mlrun. При вызове mlrun пользователь указывает число необходимых для счета процессов, максимальное время счета и имя, а при наличии и параметры, программы-функции. Команда mlrun в интерактивном текстовом режиме (-nodisplay) вызывает программу matlab для выполнения функции imm_sch_f (scheme function на рисунке), передавая ей все необходимые аргументы.
    2) Обеспечить наличие скрипта, реализующего механизм постановки в очередь программы пользователя, сформированной для запуска на кластере в рамках Matlab. Этот скрипт назван matlab_run.

    Используем предлагаемую на сайте Matlab схему запуска программы пользователя на кластере для демонстрации получаемой у нас цепочки вызовов (для определенности на um64 в системе пакетной обработки заданий СУППЗ, 2009 г.).

    center

    Источниками для написания собственных функций и скриптов послужили:
    1) Ориентированные на Generic Scheduler примеры:
    - функций Submit и Decode,
    - схемы программирования параллельной работы на хосте в клиентской части Matlab и
    - действий по удалению (разрушению, destroy) законченной и ненужной уже работы (Job).
    2) Документация (скрипты типа pbsParallelWrapper) в каталогах вида:
      /opt/matlab-R2009b/toolbox/distcomp/examples/integration/{pbs|ssh|lsf}
        
    где R2009b - название версии
    3) Скрипты запуска, такие как mvarun_p2 из каталога
        /common/runmvs/bin

    Список наших служебных функций и скриптов приведен в таблице:

    center

    При переходе на новую версию Matlab, например R2010a, следует
    - добавить одноименные ссылки в каталог /opt/matlab-R2010a/toolbox/local
    на наши служебные Matlab функции, хранящиеся в каталоге /opt/matlab-imm, а именно: imm_sch_f.m, imm_submitfunc.m, imm_decode.m, job_destroy.m ;
    - скорректировать файл /etc/profile.d/matlab.sh.

    Запуск программ из пакета ANSYS

    ANSYS - это программный пакет конечно-элементного анализа, решающий задачи в различных областях инженерной деятельности (прочность конструкций, термодинамика, механика жидкостей и газов, электромагнетизм), включая связанные многодисциплинарные задачи (термопрочность, магнитоупругость и т.п).
    ANSYS CFX, ANSYS Fluent – самостоятельные программные продукты от ANSYS,Inc., предназначенные для решения стационарных и нестационарных задач механики жидкостей и газов.

    /common/runmvs/bin/ansysrun в настоящее время используется для запуска ansys145, cfx5solve и fluent.
    Вызов ansysrun без параметров выдает краткую информацию об использовании.

    Внимание!
    Команды настройки переменных окружения содержатся в файле /common/runmvs/conf/ansys_env.sh, поэтому строка
          . /common/runmvs/conf/ansys_env.sh

    должна быть в ~/.bashrc.

    При отсутствии этой строки выдается диагностика и постановки задания в очередь не происходит.

    Примеры.

    Запуск ansys145 с 12-ю процессами на 60 минут для выполнения ANSYS-скрипта ansys_s1:
          ansysrun -np 12 -maxtime 60 -stdin ansys_s1 ansys145

    Запуск на 30 минут ansys145 с 8-ю процессами и использованием GPU с соответствующим увеличением памяти до 3 ГБ (на один процесс) для выполнения ANSYS-скрипта ansys_s2:
          ansysrun -np 8 -gpu 8 -m 3G -maxtime 30 -stdin ansys_s2 ansys145

    Запуск cfx5solve по 6 (=np/nh) процессов на двух узлах на 100 минут для выполнения bench.def (def-файл ANSYS):
          ansysrun -np 12 -nh 2 -maxtime 100 cfx5solve -def bench.def 

    Запуск fluent c 16 процессами на 400 минут для выполнения my.cav (cav-файл ANSYS) с дополнительным параметром 3ddp:
          ansysrun -np 16 -maxtime 400 fluent 3ddp -i my.cav

    Инструментарий программиста в Linux: MAKE

    make

    Утилита автоматически определяет, какие части большой программы должны быть перекомпилированы и команды для их перекомпиляции. Наиболее часто make используется для компиляции C-программ и содержит особенности ориентированные именно на такие задачи, но можно использовать make с любым языком программирования. Более того, применение утилиты make не ограничивается программами. Можно использовать еe для описания любой задачи, где некоторые файлы должны автоматически порождаться из других всегда, когда те изменяются.

    make-file

    Прежде чем использовать make, необходимо создать файл, называемый make-файлом, который описывает отношения между файлами Вашей программы и содержит команды для обновления каждого файла. Обычно исполняемый файл зависит от объектных файлов, которые, в свою очередь, зависят от исходных файлов и файлов заголовков. Для имени make-файла рекомендуется название  GNUmakefile, makefile или Makefile, причем поиск идет именно в указанном порядке. Если необходимо использовать нестандартное имя, то его можно передать явно через опцию -f.
    Когда make-файл уже написан, достаточно выполнить в каталоге в котором он находится команду make. Простой make-файл состоит из правил(инструкций) следующего вида:

    ПЕРЕМЕННАЯ = ЗНАЧЕНИЕ ... ЦЕЛЬ ... : ЗАВИСИМОСТЬ ...            КОМАНДА 1
               КОМАНДА 2 ПЕРЕМЕННАЯ = ЗНАЧЕНИЕ ... ЦЕЛЬ ... : ЗАВИСИМОСТЬ ...            КОМАНДА 1            КОМАНДА 2
    и т.д.

    ЦЕЛЬ обычно представляет собой имя файла, генерируемого программой make. Примерами целей являются исполняемые или объектные файлы. Цель может также быть именем выполняемого действия, как, например, clean.
    ЗАВИСИМОСТЬ - это файл, изменение которого служит признаком необходимости цели. Часто цель зависит от нескольких файлов. КОМАНДА - это действие, которое выполняет make. Правило может иметь более чем одну команду - каждую на своей собственной строке. Важное замечание: необходимо начинать каждую строку, содержащую команды, с символа табуляции. Длинные строки разбиваются на несколько с использованием обратного слэша, за которым следует перевод строки. Знак диез # является началом комментария. Строка с # до конца игнорируется. Комментарии могут переноситься на несколько строк с помощью обратного слэша в конце строки.

    Запуск make

    Синтаксис:

    make [Опции] [Переменная='abc'] [Цель]

    Квадратные скобки означают необязательность присутствия данной части.
    Цель - имя цели, которую надо выполнить.
    Переменная ='abc' -переопределение переменных. Значения переменных введенных в командной строке имеют больший приоритет, чем определения в make-файле.
    Опции:
    -f file - явное задание имени make-файла, если задание опущено, то ищутся файлы GNUmakefile, makefile или Makefile.
    -n - имитация действий без реального выполнения, служит для отладки.
    -t - изменение времени модификации цели без реального выполнения.
    -q - проверка на необходимость обновления цели без реального выполнения.

     

    Более сложные способы применения MAKE

    Правила написания Makefile

    Порядок правил несущественен. По умолчанию главной целью make является цель первого правила в первом make-файле. Если в первом правиле есть несколько целей, то только первая цель берется в качестве цели по умолчанию. Цель, начинающаяся с точки, не используется как цель по умолчанию, если она не содержит  один или более символа '/' т.е. определяет путь к файлу; кроме того, по умолчанию не используются цели, определяющие шаблонные правила.
    В качестве ЦЕЛИ или ЗАВИСИМОСТИ может использоваться список файлов через пробел или шаблон в стиле shell.
    Шаблоны интерпретируются в момент выполнения правила, при присваивании переменным интерпретация шаблона не происходит, для присваивания списка файлов переменной используется специальная функция wildcard.


    objects := $(wildcard *.o
    edit: *.o
         cc -o edit *.o

    Для автоматической генерации зависимостей от файлов заголовков в языке СИ можно использовать команду gcc -M file.c или gcc -MM file.c. Второй вариант не генерирует зависимости от системных заголовочных файлов. В КОМАНДАХ можно использовать автоматические переменные. Эти переменные имеют значения, заново вычисленные для каждого выполняемого правила на основе цели и зависимостей правила.

    Автоматическая переменная Назначение
    $@ Имя файла цели правила. В шаблонном правиле с несколькими целями,имя той цели, которая вызвала выполнение команд правила.
    $< Имя первой зависимости. Если цель получила свои команды из неявного правила, то это будет первая зависимость, добавленная неявным правилом.
    $? Имена всех зависимостей, которые являются более новыми, чем цель, с  пробелами между ними.
    $^ Имена всех зависимостей, с пробелами между ними. Если Вы для цели неоднократно укажете одну и ту же зависимость, значение переменной '$^' будет содержать только одну копию ее имени.
    $+ Эта переменная аналогична переменной '$^', только зависимости, указанные неоднократно дублируются в том порядке, в котором они указаны в make-файле. Это в первую очередь полезно для использования в командах компоновки, где является существенным повторение имен библиотек в определенном порядке
    $* База с которой сопоставляется неявное правило (см. ниже). В шаблонном правиле база представляет собой часть имени файла, которая сопоставляется символу '%' в шаблоне цели. Если целью является файл 'dir/a.foo.b', а   шаблон цели - 'a.%.b', то базой будет 'dir/foo'. База полезна для создания имен файлов, связанных с правилом. В явных правилах база не определена как имя файла без расширения,если такое расширение можно выделить. Не рекомендуется использовать эту переменную в явных правилах

    Неявные правила

    Неявные правила определены для многих языков программирования и применяются в соответствии с расширением исходного файла. По умолчанию список расширений такой : .out, .a, .ln, .o, .c, .cc, .C, cpp, .p, .f, .F, .r, .y, .l, .s, .S, .mod, .sym, .def, .h, .info, .dvi, .tex, .texinfo, .texi, .txinfo, .w, .ch, .web, .sh, .elc, .el. При использовании неявных правил используются переменные, переопределяя которые можно управлять процессом преобразования файлов, например, указывать нестандартный компилятор или передавать ему опции.

    Исходный файл Порожденный файл Команда
      Компиляция C-программ 'file.c' 'file.o' $(CC) -c $(CPPFLAGS) $(CFLAGS) file.c
      Компиляция программ на языке C++
    'file.cc'
    или 'file.C'
    'file.o'  $(CXX) -c $(CPPFLAGS) $(CXXFLAGS) file .cc
      Компиляция программ на Фортране
    'file.f'
    'file.o' $(FC) -c $(FFLAGS) file .f

     

    Пример MakeFile

    Пример makefile

    Использование действий по умолчанию.

    #default target - file edit
    edit : main.o kbd.o command.o display.o \
            insert.o search.o files.o utils.o
             cc -o edit main.o kbd.o command.o display.o \
                        insert.o search.o files.o utils.o

    main.o : main.c defs.h
            cc -c main.c
    kbd.o : kbd.c defs.h command.h
            cc -c kbd.c
    command.o : command.c defs.h command.h
            cc -c command.c
    display.o : display.c defs.h buffer.h
            cc -c display.c
    insert.o : insert.c defs.h buffer.h
            cc -c insert.c
    search.o : search.c defs.h buffer.h
            cc -c search.c
    files.o : files.c defs.h buffer.h command.h
            cc -c files.c
    utils.o : utils.c defs.h
            cc -c utils.c
    clean :
           rm edit main.o kbd.o command.o display.o \
              insert.o search.o files.o utils.o

    По умолчанию, make начинает с первого правила (не считая правил, имена целей у которых начинаются с '.'). Это называется главной целью по умолчанию. В нашем случае это правило edit. Если файл edit новее чем объектные файлы, от которых он зависит, то ничего не произойдет. В противном случае, прежде чем make сможет полностью обработать это правило, он должен рекурсивно обработать правила для файлов, от которых зависит edit. Каждый из этих файлов обрабатывается в соответствии со своим собственным правилом. Перекомпиляция должна быть проведена, если исходный файл или любой из заголовочных файлов, упомянутых среди зависимостей, обновлен позднее, чем объектный файл, или если объектный файл не существует.
    Правилу clean не соответствует никакого создаваемого файла и, соответственно, clean ни от чего не зависит и само не входит в список зависимостей. При запуске по умолчанию clean вызываться не будет. Для его выполнения необходимо явно указать цель при запуске make: make clean
    Для сокращения записи можно использовать переменные и действия по умолчанию (неявные правила)

    objects = main.o kbd.o command.o display.o \
              insert.o search.o files.o utils.o

    edit : $(objects)
            cc -o edit $(objects)
    main.o : defs.h
    kbd.o : defs.h command.h
    command.o : defs.h command.h
    display.o : defs.h buffer.h
    insert.o : defs.h buffer.h
    search.o : defs.h buffer.h
    files.o : defs.h buffer.h command.h
    utils.o : defs.h
    .PHONY : clean
    clean :
            -rm edit $(objects)

    Переменная objects позволила использовать единожды написанный список объектных файлов, а для объектных файлов в make встроено неявное правило по умолчанию

    file.c: file.o   cc -c file.c

    Специальная цель .PHONY является встроенной в make и определяет свои зависимости как цели-имена, которым нет соответствия в виде файлов. Если данное правило пропустить, то создание в текущем каталоге файла с именем clean заблокирует выполнение make clean.
    Использование правил по умолчанию позволяет изменить стиль записей зависимостей:

    objects = main.o kbd.o command.o display.o \
              insert.o search.o files.o utils.o

    edit : $(objects)
           cc -o edit $(objects)

    $(objects) : defs.h
    kbd.o command.o files.o : command.h
    display.o insert.o search.o files.o : buffer.h

    Данная запись указывает, что все объектные файлы зависят от заголовочного файла defs.h, но для некоторых из них проверяются дополнительные зависимости.

    Работа с MPI (ссылки)