Контекст
Мое распределенное приложение C++ включает в себя значительную замену объемы данных (например, 64 ГиБ) между VRAM (очень мощных) графических процессоров CUDA. Пользователь может скомпилировать с помощью «обычного» MPI, или MPI с поддержкой CUDA, и логика взаимодействующего кода будет выглядеть следующим образом:
Код: Выделить всё
function swapGPUArrays():
if MPI is CUDA-aware:
exchange VRAM pointers directly
else:
cudaMemcpy VRAM to RAM
exchange RAM pointers
cudaMemcpy RAM to VRAM
Код: Выделить всё
function exchangeArrays():
partition arrays into maximum-sized MPI messages (about `16 GiB`)
asynchronously send/recv each message
wait for all asynchs to finish
Этот код отлично работает в следующих сценариях:
- используется MPI-компилятор, не поддерживающий CUDA; обмен памятью осуществляется через RAM
- используется MPI-компилятор с поддержкой UCX и CUDA; обмен указателями VRAM осуществляется напрямую, причем «за кулисами» это делается с использованием оптимизированных методов (например, одноранговая прямая связь между графическими процессорами, если это разрешено такими вещами, как NVLink).
Проблема
Рассмотрим сценарий, в котором пользователь компилирует этот код с помощью MPI с поддержкой CUDA, но его графические процессоры нет напрямую подключен к сети/межсоединению. Это означает, что во время выполнения вызовы sendrecv MPI, поддерживающего CUDA, будут тайно маршрутизировать сообщения через ОЗУ, аналогично моему коду выше. Это работает правильно, но, увы, у них недостаточная производительность! - В моей ручной копии я cudaMemcpy полностью данных из VRAM в RAM за один вызов. Затем я разделяю данные на отдельные сообщения между RAM.
- MPI с поддержкой CUDA создает копии из VRAM в RAM для каждого сообщения. Выполнение уже достигло функции ExchangeArrays() и разделило полезную нагрузку на сообщения, прежде чем MPI решит скопировать их в ОЗУ.
Ищу решение
Если бы я заранее знал, что MPI с поддержкой CUDA в любом случае собирался маршрутизироваться через ОЗУ, я мог бы сделать это самостоятельно с помощью единственного вызова cudaMemcpy. Поэтому я ищу такую функцию, как
Код: Выделить всё
isMpiGoingToRouteThroughRAM()
Код: Выделить всё
if (MPI is CUDA-aware) and (not isMpiGoingToRouteThroughRAM()):
...
Все предложения приветствуются!
Вопрос по теме
Когда MPI с поддержкой CUDA возвращается к маршрутизации через ОЗУ, ему обязательно нужны буферы ОЗУ для отправки/получения сообщений в/из. Я не передаю указатель оперативной памяти при вызове sendrecv — это расточительное выделение и уничтожение временной оперативной памяти? Это была бы еще одна катастрофа, которой я хотел бы избежать!
Подробнее здесь: https://stackoverflow.com/questions/782 ... hrough-ram