Всегда ли nVidia RDMA GPUDirect работает только с физическими адресами (в физическом адресном пространстве ЦП)?

Как мы знаем: http://en.wikipedia.org/wiki/IOMMU

Пейджинг периферийной памяти может поддерживаться IOMMU. Периферийное устройство, использующее расширение интерфейса запросов страниц (PRI) PCIe SIG, может обнаружить и сигнализировать о необходимости услуг диспетчера памяти.

Но когда мы используем nVidia GPU с CUDA >= 5.0, мы можем использовать RDMA GPUDirect и знать, что:

http://docs.nvidia.com/cuda/gpudirect-rdma/index.html

Традиционно ресурсы, такие как окна BAR, сопоставляются с адресным пространством пользователя или ядра с использованием MMU ЦП в качестве адресов ввода-вывода с отображением в памяти (MMIO). Однако, поскольку в современных операционных системах нет достаточных механизмов для обмена регионами MMIO между драйверами, драйвер ядра NVIDIA экспортирует функции для выполнения необходимых преобразований и сопоставлений адресов.

http://docs.nvidia.com/cuda/gpudirect-rdma/index.html

RDMA для GPUDirect в настоящее время основывается на том, что все физические адреса одинаковы с точки зрения устройств PCI. Это делает его несовместимым с IOMMU, и, следовательно, они должны быть отключены для работы RDMA для работы GPUDirect.

И если мы выделим и отобразим CPU-RAM на UVA, как здесь:

#include <iostream>
#include "cuda_runtime.h"
#include "device_launch_parameters.h"

int main() {
    // Can Host map memory
    cudaSetDeviceFlags(cudaDeviceMapHost);  

    // Allocate memory
    unsigned char *host_src_ptr = NULL;
    cudaHostAlloc(&host_src_ptr, 1024*1024, cudaHostAllocMapped);
    std::cout << "host_src_ptr = " << (size_t)host_src_ptr << std::endl;

    // Get UVA-pointer
    unsigned int *uva_src_ptr = NULL;
    cudaHostGetDevicePointer(&uva_src_ptr, host_src_ptr, 0);
    std::cout << "uva_src_ptr  = " << (size_t)uva_src_ptr << std::endl;

    int b;  std::cin >> b;
    return 0;
}

Мы получаем равные указатели в Windwos7x64, это означает, что cudaHostGetDevicePointer() ничего не делать:

host_src_ptr = 68719476736

uva_src_ptr = 68719476736

Что означает "достаточные механизмы для обмена областями MMIO между драйверами", какой механизм здесь имеется в виду и почему я не могу использовать IOMMU, используя виртуальный адрес для доступа через PCIe к физической области BAR - другого устройства отображения памяти через PCIe?

Означает ли это, что RDMA GPUDirect всегда работает только с физическими адресами (в физическом адресном пространстве ЦП), но почему мы отправляем функцию ядра? uva_src_ptr который равен host_src_ptr простой указатель в виртуальном адресном пространстве процессора?

1 ответ

Решение

IOMMU очень полезен тем, что предоставляет набор регистров отображения. Он может организовать отображение любой физической памяти в пределах диапазона адресов, доступного для устройства, и это может привести к тому, что физически разбросанные буферы будут выглядеть смежными с устройствами. Это не подходит для сторонних карт PCI/PCI-Express или удаленных компьютеров, пытающихся получить доступ к исходному физическому смещению графического процессора nVidia, так как это может привести к тому, что фактически не будет получен доступ к намеченным областям памяти или будет запрещен / ограничен такой доступ со стороны пользователя. -карточное основание подразделением IOMMU. Это должно быть отключено, потому что

"RDMA для GPUDirect в настоящее время полагается на то, что все физические адреса одинаковы с точки зрения устройств PCI".

-nVidia, Особенности проектирования для rDMA и GPUDirect

Когда драйверы пытаются использовать MMU ЦП и отображать области отображенного в память ввода-вывода (MMIO) для использования в пространстве ядра, они обычно сохраняют возвращенный адрес из отображения памяти на себя. Поскольку каждый драйвер работает в своем собственном контексте или пространстве имен, обмен этими сопоставлениями между драйвером (ами) nVidia и драйверами других сторонних поставщиков, которые хотят поддерживать rDMA+GPUDirect, будет очень трудным и приведет к решению для конкретного поставщика (возможно, даже к продукту). - конкретно, если драйверы сильно различаются между продуктами сторонних производителей). Кроме того, современные операционные системы в настоящее время не имеют хорошего решения для обмена отображениями MMIO между драйверами, поэтому nVidia экспортирует несколько функций, которые позволяют сторонним драйверам легко получать доступ к этой информации из самого пространства ядра.

nVidia обеспечивает использование "физической адресации" для доступа к каждой карте через rDMA для GPUDirect. Это значительно упрощает процесс перемещения данных с одного компьютера на шину PCI-Express удаленной системы, используя схему физической адресации этой машины, не беспокоясь о проблемах, связанных с виртуальной адресацией (например, преобразование виртуальных адресов в физические). У каждой карты есть физический адрес, по которому она находится, и доступ к ней возможен по этому смещению; к стороннему драйверу, пытающемуся выполнить операции rDMA, нужно добавить лишь небольшую часть логики. Кроме того, эти 32- или 64-битные регистры базовых адресов являются частью стандартного пространства конфигурации PCI, поэтому физический адрес карты можно легко получить, просто считав из ее BAR, а не получая сопоставленный адрес, полученный драйвером nVidia. после прикрепления к карте. Универсальная виртуальная адресация nVidia (UVA) заботится о вышеупомянутых сопоставлениях физических адресов с, казалось бы, непрерывной областью памяти для приложений пользовательского пространства, например:

CUDA Виртуальное адресное пространство

Эти области памяти делятся на три типа: CPU, GPU и FREE, которые все описаны здесь.

Однако вернемся к вашему случаю использования: поскольку вы находитесь в пользовательском пространстве, у вас нет прямого доступа к физическому адресному пространству системы, а используемые вами адреса, вероятно, являются виртуальными адресами, предоставленными вам UVA nVidia., Предполагая, что никакие предыдущие выделения не были сделаны, ваше выделение памяти должно находиться в смещении +0x00000000, что приведет к тому, что вы увидите такое же смещение самого GPU. Если бы вам пришлось выделить второй буфер, я думаю, вы бы увидели, что этот буфер запускается сразу после окончания первого буфера (со смещением +0x00100000 от базового виртуального адреса графического процессора в вашем случае выделения 1 МБ).

Однако, если вы находитесь в пространстве ядра и пишете драйвер для карты вашей компании, чтобы использовать rDMA для GPUDirect, вы бы использовали 32- или 64-битные физические адреса, назначенные графическому процессору BIOS и / или ОС системы, чтобы Данные rDMA непосредственно в и из самого GPU.

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

Чтобы ответить на вопрос из заголовка вашего поста: nVidia в настоящее время поддерживает только физическую адресацию для rDMA+GPUDirect в пространстве ядра. Для приложений пользовательского пространства вы всегда будете использовать виртуальный адрес графического процессора, предоставленный вам UVA nVidia, который находится в виртуальном адресном пространстве CPU.


Относительно вашего приложения, вот упрощенная разбивка процесса, который вы можете сделать для операций rDMA:

  1. Ваше приложение пользовательского пространства создает буферы, которые входят в объем пространства унифицированной виртуальной адресации, предоставляемого nVidia (виртуальные адреса).
  2. Позвонить cuPointerGetAttribute(...) получить токены P2P; Эти токены относятся к памяти в контексте CUDA.
  3. Как - нибудь отправьте всю эту информацию в пространство ядра (например, IOCTL, чтение / запись в ваш драйвер и т. Д.). Как минимум, вы захотите, чтобы эти три вещи оказались в вашем драйвере пространства ядра:
    • P2P токены возвращены cuPointerGetAttribute(...)
    • UVA виртуальный адрес (а) буфера (ов)
    • Размер буфера (ов)
  4. Теперь переведите эти виртуальные адреса в соответствующие им физические адреса, вызвав функции пространства ядра nVidia, так как эти адреса хранятся в таблицах страниц nVidia и могут быть доступны с помощью экспортированных функций nVidia, таких как: nvidia_p2p_get_pages(...), nvidia_p2p_put_pages(...), а также nvidia_p2p_free_page_table(...),
  5. Используйте эти физические адреса, полученные на предыдущем шаге, чтобы инициализировать ваш механизм DMA, который будет управлять этими буферами.

Более подробное объяснение этого процесса можно найти здесь.

Другие вопросы по тегам