О запуске приложений с 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).

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

Пусть задано
    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