VASP с ускорением на GPU

Ознакомьтесь с Руководством для быстрого запуска и начните работу.

VASP

VASP (Vienna Ab Initio Simulation Package) – это программный комплекс для расчета электронной структуры в атомном масштабе с применением первопринципного подхода путем приближения решений к уравнению Шредингера. Он реализует стандартную функциональную теорию плотности, а также современные функциональные возможности, такие как гибридные функционалы, методы функций Грина (GW и ACFDT-RPA) и MP2 (теории возмущений Меллера–Плессе 2-го порядка).

VASP работает до 10 раз быстрее на графических процессорах NVIDIA Tesla P100 по сравнению с CPU-системами, позволяя прибегать к более точным и одновременно требующим большего объема вычислений методам.

VASP работает до 10 раз быстрее на GPU

Установка

Системные требования

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

  1. Intel Compiler Suite (особенно Fortran, C/C++ и MKL)
  2. Intel MPI
  3. CUDA 8.0

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

Последняя GPU-портированная версия VASP может быть скомпилирована при помощи набора компиляторов PGI, при этом версия Community Edition доступна бесплатно! Но поскольку многие пользователи VASP традиционно используют компилятор Intel, мы также будем придерживаться его в настоящем руководстве.

Загрузка и компиляция

ЗАГРУЗКА НЕОБХОДИМЫХ ИСХОДНЫХ ФАЙЛОВ

VASP – это коммерческое программное обеспечение. Если вы являетесь постоянным получателем лицензии VASP, то сможете скачать самую последнюю портированную на GPU версию ПО. Как приобрести лицензию, читайте здесь. Введите свои учетные данные справа в разделе «Портал сообщества» и нажмите «Войти», чтобы получить доступ к загрузкам. Нажмите "VASP5" и выберите папку "src". Вам необходимо скачать следующие файлы:

vasp.5.4.4.tar.gz

Регулярно посещайте официальный вебсайт VASP, чтобы получать самые последние обновления и патчи.

РАЗАРХИВАЦИЯ И КОРРЕКТИРОВКА

Для начала разархивируйте исходный код VASP, который вы скачали:

tar xfz vasp.5.4.4.tar.gz

Теперь перейдите в только что извлеченный каталог, содержащий источники, и примените патчи:

cd vasp.5.4.4

Makefile VASP требует некоторых изменений, отражающих локальную программную среду. VASP поставляется с набором шаблонов makefile для разных настроек, которые находятся во вложенной папке. Скопируйте соответствующий makefile.include из вложенной папки (в этом руководстве мы используем компилятор Intel Fortran и NVIDIA CUDA в ОС Linux):

cp arch/makefile.include.linux_intel makefile.include

Если вам необходимо адаптировать makefile.include, см. раздел Устранение неисправностей.

Большинство параметров makefile.include настроены на работу из коробки за счет обнаружения необходимых значений из ваших переменных среды. Однако настоятельно рекомендуется установить переменную GENCODE_ARCH в файл, который вы просто скопировали для установленных в вашей системе GPU. Проверьте вычислительные возможности установленных в вашей системе GPU и отредактируйте makefile.include с помощью редактора (например, nano, vim или emacs по умолчанию доступны на многих системах):

nano makefile.include

Мы используем графические карты NVIDIA P100 и компилируем программу под вычислительную возможность 6.0, чтобы добиться максимальной производительности. Исходя из этого мы не меняем строку GENCODE_ARCH по умолчанию:

GENCODE_ARCH  := -gencode=arch=compute_30,code=\"sm_30,compute_30\" \
-gencode=arch=compute_35,code=\"sm_35,compute_35\" \
-gencode=arch=compute_60,code=\"sm_60,compute_60\"

Если мы оставляем флажки на неиспользуемых вычислительных возможностях (например, 3,5) включенными, это не повредит, но позволит запускать конечные двоичные файлы на GPU других архитектур. Если ваш GPU имеет другую вычислительную возможность, обязательно измените соответствующие значения в строке. Так, например, если вы также хотите использовать V100, измените строку следующим образом (и используйте CUDA 9):

GENCODE_ARCH  := -gencode=arch=compute_30,code=\"sm_30,compute_30\" \
-gencode=arch=compute_35,code=\"sm_35,compute_35\" \
-gencode=arch=compute_60,code=\"sm_60,compute_60\" \
-gencode=arch=compute_70,code=\"sm_70,compute_70\"

Теперь соберите портированную на GPU версию VASP, исполнив (не добавляйте –j, так как VASP не поддерживает параллельную сборку):

make gpu

Если компиляция прошла успешно, в bin/vasp-gpu появится GPU-ускоренная версия VASP. Убедитесь, что двоичный файл содержит

ls -l bin/vasp-gpu

Если компиляция не удалась, обратитесь к главе “Настройка переменных сборки” в разделе Устранение неисправностей.

Теперь пора собрать версию, позволяющую выполнять неколлинеарные вычисления (когда LNONCOLLINEAR=.TRUE. или LSORBIT=.TRUE. в INCAR) при помощи gpu_ncl. Обратите внимание, что Γ point flavor в VASP еще не поддерживается на GPU.

 

Вы также можете собрать версию для вычислений только на CPU (std, ncl, gam):

make gpu_ncl std ncl gam

Это даст вам следующий список двоичных файлов, но в этом руководстве будут использоваться только vasp_gpu и, возможно, vasp_std:

Таблица 1 Обзор различных исполняемых файлов для VASP.

vasp_std Default version of VASP
vasp_ncl Special version required to run calculations with LNONCOLLINEAR=.TRUE. or LSORBIT=.TRUE. in the INCAR
vasp_gam Special version that saves memory and computations for calculations at Γ only.
vasp_gpu Same as vasp_std, but with GPU acceleration
vasp_gpu_ncl Same as vasp_ncl, but with GPU acceleration

Рекомендуем устанавливать двоичные файлы VASP не в каталог сборки, например, в ~/bin:

mkdir -p ~/bin
cp bin/vasp* ~/bin

УСТАНОВКА БАЗЫ ДАННЫХ POTCAR

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

Введите свои учетные данные справа в разделе «Портал сообщества» и нажмите «Войти», чтобы получить доступ к загрузкам. Затем нажмите “Потенциалы” и выберите “LDA”. Скачайте все предложенные файлы и проделайте то же самое для папок “PBE” и “PW91”.

Вы получите следующий набор файлов:

  1. potpaw_PBE.tgz
  2. potpaw_PBE.54.tar.gz
  3. potpaw_PBE.52.tar.gz
  4. potpaw_LDA.tgz
  5. potpaw_LDA.54.tar.gz
  6. potpaw_LDA.52.tar.gz
  7. potpaw_GGA.tar.gz
  8.  potUSPP_LDA.tar.gz
  9. potUSPP_GGA.tar.gz

Разархивируйте их, используя скрипт: extractPOTCARs.sh.

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

Запуск задач

GPU-ускоренные вычисления в VASP

В главном файле управления INCAR есть несколько опций, которые требуют особого внимания в версии VASP для вычислений на GPU. Вы получите сообщения об ошибках и предупреждения, если настройки в файле INCAR не поддерживаются.

Не игнорируйте эти сообщения и реагируйте соответственно! В этом разделе поясняются настройки INCAR, которые имеют отношение к GPU.

Ограничьтесь использованием следующих опций для флажка ALGO:

  1. Normal
  2. Fast
  3. Veryfast

Другие алгоритмы, доступные в VASP, не были широко протестированы и могут даже привести к неправильным результатам. Кроме того, необходимо использовать следующие параметры в файле INCAR:

  1. LREAL = .TRUE. или LREAL = A
  2. NCORE = 1

Чтобы начать работу, мы предлагаем несколько примеров расчетов. Мы будем использовать их, чтобы показать, как достичь более высокой производительности по сравнению с простыми настройками. Файлы с примерными входными данными можно найти в git-репозитории. Перейдите в нужный каталог и быстро просмотрите файл INCAR, чтобы убедиться, что он соответствует указанным выше вариантам:

cd gpu-vasp-files/benchmarks

По причинам, связанным с авторскими правами, необходимо самостоятельно создавать необходимые файлы POTCAR. Предположим, что вы загрузили и извлекли базу данных псевдопотенциалов как показано, и используете ~ / vasp / potcars / в качестве каталога, в котором они находятся. Файлы с примерными входными данными поставляются со скриптом, который автоматически генерирует данные, но он должен знать путь к вашей базе данных POTCAR:

cd siHugeShort
bash generatePOTCAR.sh ~/vasp/potcars

Теперь вы готовы начать вычисления в VASP с ускорением на GPU:

~/bin/vasp_gpu

Это запустит только один процесс, который будет использовать только один GPU и одно ядро CPU, независимо от того, сколько их доступно в вашей системе. Запуск вычислений подобным образом может занять много времени, но гарантирует работу без ошибок. Чтобы убедиться, что GPU активно используется, введите

nvidia-smi -l

в терминал, подключенный к тому же узлу, на котором выполняется процесс. На экране вы увидите запущенный в VASP процесс и насколько для его выполнения используется GPU. Закрыть этот экран можно нажатием клавиш CTRL+c.

Использование одного вычислительного узла

Как и стандартная версия VASP, версия с ускорением на GPU может распределять вычислительную нагрузку между несколькими CPU, GPU и узлами. В настоящем руководстве мы будем использовать Intel MPI, но все описанные здесь методы также работают с другими реализациями MPI. Обратитесь к документации соответствующей реализации MPI, чтобы найти эквивалентные опции командной строки.

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

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

Для начала взглянем, сколько (и какие) GPU установлены в вашем узле:

nvidia-smi –L

The output of the command tells us that we have 4 Tesla P100 GPUs available and lists their unique identifiers (UUID) that we will use later on:

GPU 0: Tesla P100-PCIE-16GB (UUID: GPU-74dff14b-a797-85d9-b64a-5293c94557a6)
GPU 1: Tesla P100-PCIE-16GB (UUID: GPU-576df4e5-8f0c-c773-23d2-7560fd29542e)
GPU 2: Tesla P100-PCIE-16GB (UUID: GPU-cff44500-e07e-afef-8231-0bdd32dde61f)
GPU 3: Tesla P100-PCIE-16GB (UUID: GPU-54c0a6db-b406-3e24-c28b-0b517549e824)

Как правило, GPU передают данные между своей и основной памятью. В мультисокетных системах скорость передачи данных зависит от пути, по которому они должны пройти. В лучшем случае между двумя отдельными областями памяти имеется прямая шина. При худшем сценарии CPU должен получить доступ к памяти, которая физически находится в модуле ОЗУ, связанном с другим сокетом процессора, а затем скопировать его в память GPU, которая (опять же) доступна только через полосу PCI-E, управляемую другим сокетом. Информацию о топологии шины можно получить с помощью следующей команды:

nvidia-smi topo -m

Поскольку GPU-ускоренная версия VASP еще не поддерживает прямую коммуникацию GPU-CPU, мы можем игнорировать большую часть выводимой на экран информации:

  GPU0 GPU1 GPU2 GPU3 mlx5_0 CPU Affinity
GPU0 X SOC SOC SOC SOC 0-15
GPU1 SOC X PHB PHB PHB 16-31
GPU2 SOC PHB X PIX PHB 16-31
GPU3 SOC PHB PIX X PHB 16-31
mlx5_0 SOC PHB PHB PHB X  

Последняя колонка под названием “CPU Affinity” важна, поскольку она говорит нам, на каких ядрах CPU запускать процессы MPI, если они взаимодействуют с определенным GPU. Мы видим, что все ядра CPU в первом сокете (0-15) могут напрямую взаимодействовать с GPU0, в то время как ядра CPU во втором сокете (16-31) покажут лучшую производительную при комбинации с GPU1, GPU2 и GPU3.

Тесты производительности

Ожидаемая производительность

Каждый раз, когда вы хотите сравнить время выполнения процессов в различных конфигурациях, необходимо избегать непредвиденных отклонений. Графические процессоры NVIDIA используют техники, позволяющие временно повышать и понижать тактовые частоты в зависимости от текущего температурного режима и вычислительной нагрузки. Хотя это хорошо экономит энергию, во время тестирования производительности это может привести к ошибочным значениям, которые могут быть вызваны более высоким расхождением между временем выполнения разных процессов. Поэтому для проведения сравнительного тестирования производительности мы попытаемся отключить его для всех карт в системе:

Закончив тестирование, вы можете перезагрузить карты, чтобы они начали работать на максимально поддерживаемых частотах:

ОТКАЗ ОТ ОТВЕТСТВЕНОСТИ ЗА ПОКАЗАНИЯ ПРОИЗВОДИТЕЛЬНОСТИ

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

Самый простой способ: Один процесс на GPU

Самый простой способ использовать все 4 GPU, присутствующих в нашей системе, - это просто запустить 4 процесса MPI в VASP и прибегнуть к автоматическому выбору, на каких ядрах CPU эти процессы будут запущены:

mpirun -n 4 ~/bin/vasp_gpu

Среда Intel MPI автоматически привязывает процессы к определенным ядрам CPU, поэтому операционная система не может перемещать их на другие ядра во время выполнения задачи, таким образом предотвращая некоторые неблагоприятные сценарии перемещения данных. Тем не менее, это может по-прежнему приводить к условно оптимальному решению, поскольку реализация MPI не знает топологии GPU. Мы можем подробнее изучить процесс привязки к ядрам CPU путем повышения детализации:

mpirun -n 4 -genv I_MPI_DEBUG=4 ~/bin/vasp_gpu

Изучая полученный вывод и сравнивая его с выводами о топологии межсоединений, мы видим некоторые проблемы:

...

[0] MPI startup():
Rank
Pid
Node name
Pin cpu

 
[0] MPI startup():
0
41587
hsw227
{16,17,18,19,20,21,22,23}

 
[0] MPI startup():
1
41588
hsw227
{24,25,26,27,28,29,30,31}

 
[0] MPI startup():
2
41589
hsw227
{0,1,2,3,4,5,6,7}

 
[0] MPI startup():
3
41590
hsw227
{8,9,10,11,12,13,14,15}


Using device 0 (rank 0, local rank 0, local size 4) : Tesla P100-PCIE-16GB

Using device 1 (rank 1, local rank 1, local size 4) : Tesla P100-PCIE-16GB

Using device 2 (rank 2, local rank 2, local size 4) : Tesla P100-PCIE-16GB

Using device 3 (rank 3, local rank 3, local size 4) : Tesla P100-PCIE-16GB

...

Ранг 0 использует GPU0, но привязан к более отдаленным ядрам CPU 16-23. Та же самая проблема наблюдается с рангами 2 и 3. Только ранг 1 использует GPU1 и привязан к ядрам 24-31, что обеспечивает максимальную производительность передачи данных.

Давайте посмотрим на некоторые фактические показатели производительности. Используя все 32 ядра двух процессоров Intel® Xeon® E5-2698 v3, установленных в нашей системе без ускорения на GPU, нам потребовалось 607,142 с для выполнения теста siHugeShort .1 Использование 4 GPU приводит к времени выполнения в 273,320 с и обеспечивает ускорение в 2,22 раз. Используйте следующие показатели, включенные в VASP, чтобы быстро узнать, сколько времени заняли ваши вычисления

1 Если вы собрали версию VASP для вычислений на CPU, вы можете использовать следующую команду: mpirun -n 32 -env I_MPI_PIN_PROCESSOR_LIST=allcores:map=scatter ~/bin/vasp_std

grep Elapsed\time OUTCAR

VASP привязывает GPU к MPI-рангам последовательно, пропуская GPU с недостаточной вычислительной возможностью (если таковые имеются в системе). Благодаря этому и используя следующий синтаксис, мы можем вручную управлять размещением процессов на CPU и распределять ранги, чтобы каждый процесс использовал GPU с самым коротким путем передачи данных:

mpirun -n 4 -genv I_MPI_DEBUG=4 -env I_MPI_PIN_PROCESSOR_LIST=0,16,21,26 ~/bin/vasp_gpu

Этот способ не дает улучшения в нашей системе (время выполнения – 273,370 с) , что, вероятно, вызвано несбалансированным использованием общих ресурсов CPU, таких как пропускная способность памяти и кеширование (3 процесса используют один CPU). Вы можете распределять ранги равномерно по сокетам процессора, но только один ранг должен использовать медленный путь передачи данных памяти:

mpirun -n 4 -genv I_MPI_DEBUG=4 -env I_MPI_PIN_PROCESSOR_LIST=0,8,16,24 ~/bin/vasp_gpu

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

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

mpirun -n 4 -genv I_MPI_DEBUG=4 -env I_MPI_PIN_PROCESSOR_LIST=allcores:map=scatter ~/bin/vasp_gpu

Это обеспечило нам время работы в 276,299 с и может быть особенно полезно, если некоторые из ядер процессора бездействуют. Вы можете сделать это специально, если один процесс на один GPU полностью поглощает его ресурсы, что ограничивает производительность. Еще большая перегрузка GPU приведет к снижению производительности. Это хорошо видно на примере тестирования siHugeShort. Однако, как правило, тратить имеющиеся ядра CPU впустую - плохая идея, если вы не перегружаете GPU, поэтому советуем провести собственное тестирование!

Второй самый простой способ: несколько процессов на GPU

Чтобы продемонстрировать, как использовать больше ядер CPU, чем доступно GPU, мы перейдем к другому тесту под названием silicaIFPEN. На его выполнение при использовании только 32 ядер CPU уходит 710,156 с. Использование 4 графических процессоров P100 с одним MPI рангом на GPU позволяет выполнить тест за 241,674 с (ускорение в 2,9 раз). Графические процессоры могут использоваться сразу несколькими процессами. Чтобы использовать эту возможность, мы должны убедиться, что все GPU установлены в режим вычисления по умолчанию:

Теперь мы запускаем вычисления:

mpirun -n 8 -env I_MPI_PIN_PROCESSOR_LIST=0,8,16,24,4,12,20,28 ~/bin/vasp_gpu

В silicaIFPEN время выполнения 12 процессов на системе с 4 GPU P100 улучшилось до 211,576 с (т.е. 3 процесса на GPU), что означает повышение ускорения до 3,36 раз. Хотя выполнение 4 и более процессов на одном GPU может иметь и обратный эффект. Приведенные ниже в таблице данные так же показывают, что размещение рангов вручную не приносит повышения производительности.

Таблица 2 Сравнение времени выполнения в silicaIFPEN при разном количестве MPI процессов на GPU

MPI ranks per GPU Total MPI ranks Elapsed time (map:scatter) Elapsed time (map:ideal)
0 32 (CPU only) 710.156 s  
1 4 242.247 s 241.674 s
2 8 214.519 s 212.389 s
3 12 212.623 s 211.576 s2
4 16 220.611 s 224.013 s3
5 20 234.540 s  
6 24 243.665 s  
7 28 259.757 s  
8 32 274.798 s  

2 mpirun -n 12 -env I_MPI_PIN_PROCESSOR_LIST=0,8,16,24,3,11,19,27,6,14,22,30 ~/bin/vasp_gpu
3 mpirun -n 16 -env I_MPI_PIN_PROCESSOR_LIST=0,8,16,24,2,10,18,26,4,12,20,28,6,14,22,30 ~/bin/vasp_gpu

После достижения «золотой середины» последующее добавление процессов на GPU только ухудшает производительность. Но почему? Каждый раз, когда GPU необходимо переключать контексты, т.е. разрешать выполнение другого процесса, он вводит жесткую точку синхронизации. Следовательно, нет возможности для частичного совпадения инструкций разных процессов на GPU, и злоупотребление может привести к замедлению работы. Взгляните на изображение ниже.

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

VASP работает до 10 раз быстрее на GPU

NVIDIA MPS: перекрывание инструкций при совместном использовании GPU

Этот метод тесно связан с предыдущим, но устраняет проблему того, что инструкции нескольких процессов могут не пересекаться на GPU, как показано во второй строке на приведенном изображении. Рекомендуется переводить GPU в эксклюзивный режим при использовании MPS:

Единственное, что остается сделать, чтобы использовать эту возможность, - это запустить сервер MPS перед запуском MPI задач:

nvidia-cuda-mps-control -d
mpirun -n 8 -env I_MPI_PIN_PROCESSOR_LIST=allcores:map=scatter ~/bin/vasp_gpu
echo quit | nvidia-cuda-mps-control

Первая команда запускает сервер MPS в фоновом режиме. Когда он будет запущен, он будет перехватывать инструкции процессов, совместно использующих один GPU, и помещать их в один и тот же контекст, прежде чем отправлять их на GPU. Разница с предыдущим разделом заключается в том, что с точки зрения GPU инструкции относятся к одному процессу и контексту, а значит, могут перекрываться, как если бы вы использовали потоки в приложении CUDA. С помощью nvidia-smi -l вы можете убедиться, что только один процесс имеет доступ к GPU.

Этот режим в VASP может помочь увеличить использование GPU, когда один процесс не насыщает его ресурсы. Чтобы продемонстрировать это, мы приводим третий пример B.hR105, вычисление с использованием точного обмена внутри HSE06-функционала. Мы запускали его с разным количеством рангов MPI на каждый GPU каждый раз с включенным MPS и без него.

Таблица 3 Сравнение времени выполнения B.hR105 при разном количестве MPI процессов на GPU с включенным MPS и без для NSIM=4.

MPI ranks per GPU Total MPI ranks Elapsed time without MPS Elapsed time with MPS
0 32 (CPU only) 1027.525 s
1 4 213.903 s 327.835 s
2 8 260.170 s 248.563 s
4 16 221.159 s 158.465 s
7 28 241.594 s 169.441 s
8 32 246.893 s 168.592 s

Самое главное, что MPS увеличивает время выполнения на 55,4 с (на 26%) до 158,465 с по сравнению с лучшим результатом без MPS (213,903 с). Запуск процессов, равных по количеству числу доступных ядер CPU, дает лучшую производительность при использовании MPS.

Мы намеренно пропустили вычисления с 3, 5 и 6 рангами на каждый GPU, потому что количество полос (224), используемое в этом примере, не делится на результирующее число рангов и, следовательно, автоматически увеличивается в VASP, что приводит к увеличению нагрузки. Если вы заинтересованы в максимально быстрых вычислениях, мы предлагаем немного поэкспериментировать с параметром NSIM. Установив его на 32 и используя только 1 процесс на GPU (следовательно, без MPS), мы смогли увеличить время вычисления до 108,193 с, что примерно в 10 раз быстрее.

Продвинутый метод: Один MPS инстанс на GPU

Для некоторых настроек, особенно в более старых версиях CUDA, может быть полезно запустить несколько MPS-демонов, например, один сервер MPS на один GPU. Однако это требует больше усилий, так как необходимо указать для каждого MPI процесса, какой сервер MPS необходимо использовать, и каждый MPS сервер должен быть привязан к другому GPU. Мы особенно советуем этот метод вычислений на графических ускорителях P100 с CUDA 8.0. Вы можете использовать следующие скипты для запуска MPS инстансов:

Чтобы этот метод работал, программу нужно запускать, используя сценарий оболочки. Это задает переменные среды, чтобы каждый процесс использовал правильный инстанс MPS серверов, которые мы запустили: runWithMultipleMPSservers-RR.sh.

Этот скрипт в основном генерирует список путей для установки переменных среды, которые определяют, какой инстанс MPS используется. Четвертая последняя строка (myMpsInstance = ...) затем выбирает этот инстанс в зависимости от локального ID процесса MPI. Мы решили распределить процессы с 1 по 4 на графические процессоры с GPU0 по GPU3. Процесс 5 снова использует GPU 0, процесс 9 – тоже, тогда как процесс 6 и 10 привязаны к GPU 2 и так далее. Если вы использовали другой путь для установки бинарного файла VASP GPU, убедитесь, что вы адаптируете строку, начинающуюся с runCommand, соответствующим образом. Приступим к вычислениям:

mpirun -n 16 -env I_MPI_PIN_PROCESSOR_LIST=allcores:map=scatter ./runWithMultipleMPSservers-RR.sh

При использовании MPS имейте в виду, что сами сервер(-ы) MPS использует(ют) CPU. Следовательно, когда вы запускаете столько процессов, сколько у вас доступно ядер CPU, это может также перегрузить ваш CPU. Поэтому стоит оставить один или два ядра для MPS.

После завершения вычислений следующий скрипт очищает инстансы MPS:

Использование нескольких вычислительных узлов

ОДИН ПРОЦЕСС НА GPU

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

hsw224
hsw225

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

mpirun -f hostfile -n 8 -ppn 4 -genv I_MPI_DEBUG=4 -env I_MPI_PIN_PROCESSOR_LIST=0,8,16,24 ~/bin/vasp_gpu

Вывод отладки реализации MPI говорит о том, что все процессы распределены между двумя узлами, как мы и ожидали:

[0] MPI startup(): Rank Pid Node name Pin cpu
[0] MPI startup(): 0 38806 hsw224 0
[0] MPI startup(): 1 38807 hsw224 8
[0] MPI startup(): 2 38808 hsw224 16
[0] MPI startup(): 3 38809 hsw224 24
[0] MPI startup(): 4 49492 hsw225 0
[0] MPI startup(): 5 49493 hsw225 8
[0] MPI startup(): 6 49494 hsw225 16
[0] MPI startup(): 7 49495 hsw225 24

Вывод VASP подтверждает, что GPU тоже привязаны к MPI рангам:

Устройство 0 (rank 0, local rank 0, local size 4) : Tesla P100-PCIE-16GB
Устройство 1 (rank 1, local rank 1, local size 4) : Tesla P100-PCIE-16GB
Устройство 2 (rank 2, local rank 2, local size 4) : Tesla P100-PCIE-16GB
Устройство 3 (rank 3, local rank 3, local size 4) : Tesla P100-PCIE-16GB
Устройство 0 (rank 4, local rank 0, local size 4) : Tesla P100-PCIE-16GB
Устройство 1 (rank 5, local rank 1, local size 4) : Tesla P100-PCIE-16GB
Устройство 2 (rank 6, local rank 2, local size 4) : Tesla P100-PCIE-16GB
Устройство 3 (rank 7, local rank 3, local size 4) : Tesla P100-PCIE-16GB

Тест siHugeShort получает ускорение до 258,917 , но в сравнении со временем выполнения на одном узле за  268,939 с, показывает, что использование нескольких узлов бессмысленно. Тест silicaIFPEN наоборот получает ускорение с 241,674 с до 153,401 с при переходе с 4 на 8 графических процессоров P100 при одном MPI процессе на GPU.

НЕСКОЛЬКО ПРОЦЕССОВ НА GPU

Переход на несколько узлов с несколькими процессами на один GPU является простым:

mpirun -f hostfile -n 16 -ppn 8 -genv I_MPI_DEBUG=4 -env I_MPI_PIN_PROCESSOR_LIST=0,8,16,24,4,12,20,28 ~/bin/vasp_gpu

Или если вы хотите использовать все ядра CPU:

mpirun -f hostfile -n 64 -ppn 32 -genv I_MPI_DEBUG=4 -env I_MPI_PIN_PROCESSOR_LIST=allcores:map=scatter ~/bin/vasp_gpu

Для увеличения числа рангов на один GPU тест benchIFPEN домонстрирует поведение, немного отличающееся от работы на одном узле (самая быстрая конфигурация заняла 211,576 с): Использование двух процессов на GPU совсем незначительно ускоряет время выполнения, со 153,401 при одном процессе на GPU до 149,818 с. Дальнейшая перегрузка GPU снова имеет отрицательный эффект, поскольку использование 3 процессов на GPU увеличивает время выполнения до 153,516 с, а время выполнения 64 рангов в общей сложности составляет 231,015 с. Поэтому становится очевидно, что достаточно использовать 1 или 2 процесса на GPU в каждом узле.

NVIDIA MPS НА НЕСКОЛЬКИХ УЗЛАХ

Использование одного инстанса MPS на узел типично, когда инстансы запущены. Некоторые планировщики предлагают это сделать за вас, например, SLURM иногда предлагает --cuda-mps. Если что-то подобное доступно на вашем кластере, мы настоятельно рекомендуем вам использовать эту опцию и действовать так же, как описано в предыдущем разделе.

Но что делать, если ваш планировщик не предлагает подобного решения? Необходимо убедиться, что на каждом узле запущен один (и только один) инстанс MPS, прежде чем будет запущен VASP. Для этого у нас еще один скрипт: runWithOneMPSPerNode.sh.

И вновь, если вы установили бинарный файл VASP с ускорением на GPU в другое место, пожалуйста, адаптируйте переменную runCommand в начале скрипта. Следующие переменные вычисляют локальный ранг на каждом узле, потому что реализация MPI Intel не предоставляет эту информацию. Скрипт запускает MPS-сервер для каждого первого ранга на узел, убедившись, что процесс MPS не привязан к одному и тому же ядру, после чего процесс VASP будет привязан к следующему. Этот шаг имеет решающее значение, поскольку в противном случае MPS будет ограничен, используя только одно ядро (он может использовать больше), и еще хуже конкурировать с VASP за циклы CPU в этом ядре. Скрипт продолжает выполнение VASP, а затем останавливает MPS.

Скрипт вызывается из команды mpirun, как вы уже видели в более подробном разделе. Команда mpirun работает так же, как при работе без MPS, но обратите внимание, что мы вызываем скрипт вместо двоичного кода VASP:

mpirun -f hostfile -n 24 -ppn 12 -genv I_MPI_DEBUG=4 -env I_MPI_PIN_PROCESSOR_LIST=allcores:map=scatter ./runWithOneMPSPerNode.sh

Если говорить о тесте B.hR105, MPS улучшает время выполнения на одном узле и делает то же самое и на двух узлах: включение MPS ускоряет время вычисления, и использование нескольких рангов на GPU может быть полезно до определенного момента. ”Золотой серединой» на нашей системе стало использование 4 рангов на GPU, что обеспечило время выполнения в 104,052 с. По сравнению с одиночным узлом Haswell это ускорение в 9,05 раз, а в сравнении со всеми 64 ядрами процессора, это все еще быстрее в 6,61 раза.

Если мы используем NSIM=32 с 4 рангами на GPU на каждом из двух узлов и не используем MPS, вычисления занимают всего 1,222 с.

Таблица 4 Сравнение времени выполнения B.hR105 при разном количестве MPI процессов на GPU с включенным MPS и без для NSIM=4.

MPI ranks per GPU Total MPI ranks Elapsed time without MPS Elapsed time with MPS
0 32 (CPU only – 1 node) 1027.525 s
0 64 (CPU only) 763.939 s4
1 8 127.945 s 186.853 s
2 16 117.471 s 110.158 s
4 32 130.454 s 104.052 s
7 56 191.211 s 148.662 s
8 64 234.307 s5 182.260 s

4, 5 Here 256 bands were used, which increases the workload.

VASP работает до 10 раз быстрее на GPU

Рекомендованные системные конфигурации

Конфигурация аппаратного обеспечения

Workstation

Parameter
Specs

CPU Architecture

x86_64

System Memory

32-64 GB

CPUs

8 Cores, 3+ GHz
10 cores, 2.2+ GHz
16 Cores, 2+ GHz

GPU Model

NVIDIA Quadro GP100

GPUs

2-4

Servers

Parameter
Specs

CPU Architecture

x86_64

System Memory

64-128 GB

CPUs

16+ Cores, 2.7+ GHz

GPU Model

NVIDIA Tesla P100, V100

GPUs per Node

2-4

Конфигурация программного обеспечения

Software stack

Parameter
Version

OS

Linux 64

GPU Driver

352.79 or newer

CUDA Toolkit

8.0 or newer

Compiler

PGI Compiler 16.10
Intel Compiler Suite 16

MPI

OpenMPI
Intel MPI

Устранении неисправностей

АДАПТАЦИЯ ПЕРЕМЕННЫХ (опционально)

Ваша локальная программная среда может отличаться от автоматической сборки VASP. В этом случае сборка завершится неудачно, и вам потребуется внести небольшие изменения в makefile.include. Откройте makefile.include с помощью редактора (например, nano, vim или emacs доступны во многих системах по умолчанию) и внесите необходимые изменения (см. ниже):

nano makefile.include

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

make veryclean

Ниже мы приводим несколько типичных сообщений об ошибках и советов по их исправлению:

mpiifort: Command not found

Это сообщение об ошибке просто сообщает вам, что в вашей системе MPI-совместимый компилятор Intel Fortran имеет другое имя. В makefile.include измените все вводные mpiifort на соответствующие вашей системе (например, mpif90).

# error "This Intel is for use with only the Intel compilers!"

Чтобы справиться с этой ошибкой, необходимо сделать две вещи. Сначала отредактируйте makefile.include и добавьте -ccbin=icc в переменную NVCC, чтобы строка выглядела следующим образом:

NVCC := $(CUDA_ROOT)/bin/nvcc -ccbin=icc

Затем отредактируйте второй файл:

nano src/CUDA/common.mk

Там вы увидите следующий раздел:

# Compilers

NVCC ?= $(CUDA_INSTALL_PATH)/bin/nvcc

CXX := g++ -fPIC -DADD_ -Wall -openmp -DMAGMA_WITH_MKL -DMAGMA_SETAFFINITY -DGPUSHMEM=300 -DHAVE_CUBLAS

CC := gcc -fPIC -DADD_ -Wall -openmp -DMAGMA_WITH_MKL -DMAGMA_SETAFFINITY -DGPUSHMEM=300 -DHAVE_CUBLAS

#CXX := icc -fPIC -DADD_ -Wall -openmp -DMAGMA_WITH_MKL -DMAGMA_SETAFFINITY -DGPUSHMEM=300 -DHAVE_CUBLAS

#CC := icc -fPIC -DADD_ -Wall -openmp -DMAGMA_WITH_MKL -DMAGMA_SETAFFINITY -DGPUSHMEM=300 -DHAVE_CUBLAS

LINK := g++ -fPIC

Измените следующим образом:

# Compilers

NVCC ?= $(CUDA_INSTALL_PATH)/bin/nvcc

#CXX := g++ -fPIC -DADD_ -Wall -openmp -DMAGMA_WITH_MKL -DMAGMA_SETAFFINITY -DGPUSHMEM=300 -DHAVE_CUBLAS

#CC := gcc -fPIC -DADD_ -Wall -openmp -DMAGMA_WITH_MKL -DMAGMA_SETAFFINITY -DGPUSHMEM=300 -DHAVE_CUBLAS

CXX := icc -fPIC -DADD_ -Wall -openmp -DMAGMA_WITH_MKL -DMAGMA_SETAFFINITY -DGPUSHMEM=300 -DHAVE_CUBLAS

CC := icc -fPIC -DADD_ -Wall -openmp -DMAGMA_WITH_MKL -DMAGMA_SETAFFINITY -DGPUSHMEM=300 -DHAVE_CUBLAS

LINK := g++ -fPIC

/usr/local/cuda//bin/nvcc: Command not found

Это сообщение говорит о том, что make не может найти компилятор NVIDIA CUDA nvcc. Вы можете изменить путь в строке

CUDA_ROOT := /usr/local/cuda/

или даже раскомментировать ее (используя # в качестве первого символа строки), если CUDA_ROOT задан как переменная среды.

No rule to make target `/cm/shared/apps/intel/composer_xe/2015.5.223/mkl/interfaces/fftw3xf/libfftw3xf_intel.a', needed by `vasp'. Stop.

Возможно, ваш локальный MKL был установлен без поддержки интерфейса FFTW3 как статичная библиотека. Если вы раскомментируете строку, ссылающуюся на статическую библиотеку, вставив # в начало, компоновщик потянет динамический аналог. Обязательно раскомментируйте строку (и следующую), связанную с OBJECTS_GPU, а не только ту, что идет после OBJECTS.

Моя ошибка не представлена здесь

Если ваша система соответствует требованиям, указанным в начале этого руководства, скорее всего необходимо просто изменить в makefile.include путь к библиотеке. Более подробная информация о переменных доступна по ссылке http://cms.mpi.univie.ac.at/wiki/index.php/Installing_VASP.

Соберите свою идеальную систему прямо сегодня