• A
  • A
  • A
  • АБВ
  • АБВ
  • АБВ
  • А
  • А
  • А
  • А
  • А
Обычная версия сайта

Инструкция по сборке и компиляции ПО, Python-пакетов и расширений с поддержкой различных типов GPU

👉Вернуться к списку инструкций

Базовые положения:

  1. ПО и компиляторы подключаются с использованием программного пакета Lmod. Основные команды: module available, module load, module purge
  2. В состав кластера входят узлы с различными типами GPU. Каждый тип GPU имеет собственный код CUDA compute capability: V100 (sm_70), A100 (sm_80), H100/H200 (sm_90). Эти коды используются для указания целевых архитектур при сборке.
  3. На логин-узле можно производить сборку и компиляцию даже без установленного GPU. Если ПО требует наличия nvidia-smi или выполняет тесты на GPU - выполняйте сборку на вычислительном узле с GPU.
  4. Флаги автоматической оптимизации под текущий процессор, например -xHOST у Intel или -march=native у GCC, позволяют получить более производительный исполняемый файл, но снижают его переносимость. Программа, скомпилированная с такими флагами на одном типе узлов, может не запуститься на другом типе узлов и завершиться ошибкой Illegal instruction. Если программа должна запускаться на разных типах узлов, рекомендуется использовать переносимые архитектурные флаги. Для GCC можно использовать, например, -march=x86-64-v3 -mtune=generic.
  5. Небольшие программы можно компилировать на login-узле. Сборку крупных пакетов, требующих много процессорного времени, памяти или продолжительной компиляции, рекомендуется выполнять через Slurm на вычислительном узле. Это позволяет не нагружать login-узел и одновременно собирать программу в окружении, близком к тому, в котором она будет запускаться. При этом следует помнить: если во время сборки используются флаги автоматического определения архитектуры, например -march=native, итоговый исполняемый файл будет оптимизирован под процессор именно того узла, на котором выполнялась компиляция.

CPU-only и GPU сборки

Если программа собирается с поддержкой GPU, такой исполняемый файл может требовать доступного GPU уже на этапе запуска. Даже если конкретный тестовый расчёт не использует ускоритель явно, программа может завершиться ошибкой инициализации CUDA на CPU-only узле. Поэтому рекомендуется разделять CPU-only и GPU-сборки программы:

- CPU-only сборка — для запуска на узлах без GPU;

- GPU-сборка — для запуска на узлах с GPU и соответствующими драйверами.

Для GPU-сборок в Slurm-скрипте следует явно запрашивать GPU, например: #SBATCH --gres=gpu:1 и при необходимости указывать подходящий тип узлов через constraints.

Выбор компилятора и компиляция программ

Выбор компилятора осуществляется с помощью загрузки соответствующего модуля:
module load gnu8 openmpi3
или
module load INTEL/parallel_studio_xe_2020_ce

Для компиляции параллельных MPI-приложений с помощью компиляторов Intel Parallel Studio используйте команды mpiicc, mpiicpc, mpiifort:

  • C: mpiicc [опции] -o program.out file1.c file2.c
  • C++: mpiicpc [опции] -o program.out file1.cpp file2.cpp
  • Fortran: mpiifort [опции] -o program.out file1.f90 file2.f90

Подробную информацию по использованию компиляторов Intel Parallel Studio можно получить на официальном сайте Intel.

Для компиляции параллельных MPI-приложений с помощью GNU Compiler Collection + OpenMPI используйте команды mpicc, mpixx, mpifort:

  • C: mpicc [опции] -o program.out file1.c file2.c
  • C++: mpicxx [опции] -o program.out file1.cpp file2.cpp
  • Fortran: mpifort [опции] -o program.out file1.f90 file2.f90

Подробную информацию по использованию компиляторов GNU Compiler Collection и OpenMPI можно получить на официальном сайте.

При компиляции рекомендуется указывать особые флаги оптимизаций, позволяющие ускорить выполнение программы. Флаг оптимизации -O2 активирует векторизацию и базовую оптимизацию циклов. Данный флаг в большинстве случаев обеспечивает наилучшее быстродействие работы программы.
При использовании программ с большим количеством вычислений с плавающей точкой или обрабатывающих объёмные наборы данных рекомендуется использовать флаг -O3, активирующий более агрессивное преобразование циклов и условных выражений. Более подробную информацию по флагам оптимизации можно получить на сайте Intel Parallel Studio и GNU Compiler Collection.
При компиляции с использованием компиляторов Intel также рекомендуется указывать флаг -xHOST. Он позволяет компилятору использовать максимальный набор инструкций, доступных для процессоров на суперкомпьютере. Данный флаг ещё больше оптимизирует приложение, но снижает его переносимость на другие платформы (на всех узлах вычислительного кластера НИУ ВШЭ используется процессоры одного поколения с одинаковым набором инструкций).

Пример использования флагов оптимизации при компиляции MPI-программ:
mpiicpc -xHOST -O2 /opt/ohpc/pub/examples/mpi/hello.c -o ./program_name
mpicxx -O2 /opt/ohpc/pub/examples/mpi/hello.c -o ./program_name

Для компиляции обычных (не параллельных) программ с помощью Intel Parallel Studio используйте следующие команды:

  • C: icc [опции] -o program.out file1.c file2.c
  • C++: icpc [опции] -o program.out file1.cpp file2.cpp
  • Fortran: ifort [опции] -o program.out file1.f90 file2.f90

Для компиляции обычных (не параллельных) программ с помощью GNU Compiler Collection используйте следующие команды:

  • C: gcc [опции] -o program.out file1.c file2.c
  • C++: g++ [опции] -o program.out file1.cpp file2.cpp
  • Fortran: gfortran [опции] -o program.out file1.f90 file2.f90

Компиляция С/C++/MPI/CUDA

Подключите необходимые модули, например:
module purge
module load gnu12 CUDA/12.4

При необходимости подключите дополнительные модули EasyBuild: module load EasyBuild/modules

Важно: CUDA Tookit в зависимости от версиии имеет ограничения на диапазон допустимых версий компиляторов. Подробнее можно узнать здесь и в документации CUDA.

Если код должен работать на любом типе узла с V100/A100/H100, собирайте бинарный файл с поддержкой нескольких архитектур.
Например, для cmake 3.18+:
cmake -DCMAKE_CUDA_ARCHITECTURES="70;80;90" -DCMAKE_BUILD_TYPE=Release ..
сmake --build . -j

Для nvcc:
nvcc -O3 my.cu -o app \
  -gencode arch=compute_70,code=sm_70 \
  -gencode arch=compute_80,code=sm_80 \
  -gencode arch=compute_90,code=sm_90

Важно: в зависимости от ПО ключи могут отличаться.

Компиляция Python-пакетов и cpp-расширений PyTorch

Для компиляции Python-пакетов и cpp-расширений PyTorch полезно выполнять сборку с поддержкой нескольких архитектур GPU.
В случае ручной сборки используется переменная окружения
export TORCH_CUDA_ARCH_LIST="7.0;8.0;9.0+PTX"

При использовании cmake укажите параметр в setup.py/pyproject.toml:
set(CMAKE_CUDA_ARCHITECTURES "70;80;90")

Выбор версии CUDA Toolkit

На логин-сервере и вычислительных узлах доступно несколько версий CUDA Toolkit. Все они расположены в каталоге /usr/local
Для выбора определённой версии вы можете использовать Lmod-модули CUDA/x.x, либо указывать путь вручную в переменных окружения:
export CUDA_HOME=/usr/local/cuda-12.4
export PATH=$CUDA_HOME/bin:$PATH
export LD_LIBRARY_PATH=$CUDA_HOME/lib64:$LD_LIBRARY_PATH

Эти переменные можно использовать следующим образом в cmake:
cmake -S . -B build \
  -DCMAKE_BUILD_TYPE=Release \
  -DCMAKE_CUDA_COMPILER=$CUDA_HOME/bin/nvcc \
  -DCUDAToolkit_ROOT=$CUDA_HOME \
  -DCMAKE_CUDA_ARCHITECTURES="70;80;90"
cmake --build build -j

И похожим образом в nvcc:
nvcc -O3 src/my_kernel.cu -o bin/app \
  -I$CUDA_HOME/include -L$CUDA_HOME/lib64 -lcudart \
  -Wl,-rpath,$CUDA_HOME/lib64 \
  -gencode arch=compute_70,code=sm_70 \
  -gencode arch=compute_80,code=sm_80 \
  -gencode arch=compute_90,code=sm_90

Использование заглушек библиотек при компиляции

При сборке определённого ПО необходима линковка с API драйвера NVIDIA (-lcuda, cu*) и/или библиотекой NVML (-lnvidia-ml) - эти библиотеки поставляются и работают только с установленным драйвером NVIDIA.
На логин-сервере в этом случае потребуется указать путь до заглушек библиотек (стабов), например:
LSTUBS=/usr/local/cuda/lib64/stubs
nvcc ... \
  -L$LSTUBS -lcuda -lnvidia-ml \
  -L$CUDA_HOME/lib64 -lcudart \
  -Wl,-rpath,$CUDA_HOME/lib64

Либо указать путь в LIBRARY_PATH: export LIBRARY_PATH=/usr/local/cuda/lib64/stubs:$LIBRARY_PATH
Важно: стабы - это "пустышки" библиотек для этапа линковки. На вычислительных узлах при запуске ПО должны использоваться настоящие библиотеки драйвера. Не добавляйте путь до стабов в LD_LIBRARY_PATH или rpath

Частые ошибки:

  • nvcc: command not found - не загрузили модуль CUDA, либо не добавили путь до CUDA в переменные окружения.
  • libcudart.so: cannot open shared object file - ПО во время запуска не может найти путь до библиотек CUDA. Укажите параметр -Wl,-rpath,$CUDA_HOME/lib64 на этапе сборке, либо перед запуском экспортируйте LD_LIBRARY_PATH
  • CUDA error: no kernel image is available for execution on the device - при сборке не была указана архитектура GPU, на которой выполняется запуск. Выполните сборку с указанием всех возможных архитектур GPU кластера.


 

Нашли опечатку?
Выделите её, нажмите Ctrl+Enter и отправьте нам уведомление. Спасибо за участие!
Сервис предназначен только для отправки сообщений об орфографических и пунктуационных ошибках.