CUDA VMM
Jak działa
1) cuMemGetAllocationGranularity zwraca wymaganą granulację (wyrównanie) rozmiaru alokacji dla danego urządzenia. 2) cuMemAddressReserve rezerwuje ciągły zakres wirtualnych adresów (bez pamięci fizycznej). 3) cuMemCreate tworzy uchwyt do fizycznej pamięci (backing store) o rozmiarze wielokrotności granulacji. 4) cuMemMap mapuje uchwyt fizyczny w zarezerwowanym zakresie adresów. 5) cuMemSetAccess nadaje prawa dostępu (odczyt/zapis) dla wskazanych urządzeń, co steruje też dostępem peer-to-peer. Odwrotne operacje to cuMemUnmap, cuMemAddressFree i cuMemRelease. Aby rozszerzyć alokację, rezerwuje się większy zakres adresów i domapowuje kolejne uchwyty fizyczne bez przenoszenia dotychczasowych danych. Do współdzielenia między procesami służą cuMemExportToShareableHandle i cuMemImportFromShareableHandle, operujące na uchwytach OS: deskryptorach plików w Linuksie oraz HANDLE / D3DKMT_HANDLE w Windows. CUDA nie wspiera mapowania części pojedynczej alokacji fizycznej, więc rozmiary muszą się zgadzać.
Rozwiązany problem
Wysokopoziomowe cudaMalloc łączy rezerwację adresu z fizyczną alokacją, przez co nie da się rozszerzyć istniejącej alokacji bez realokacji i skopiowania danych, a zwalnianie pamięci wymaga synchronizacji całego urządzenia. Utrudnia to budowę rosnących buforów, pul pamięci i kontroli nad fragmentacją oraz współdzieleniem pamięci między urządzeniami i procesami.
Komponenty
Rezerwuje ciągły zakres wirtualnych adresów GPU bez przypisywania pamięci fizycznej.
Tworzy uchwyt do fizycznej alokacji pamięci (backing store) o rozmiarze będącym wielokrotnością granulacji.
Mapuje uchwyt pamięci fizycznej w zarezerwowanym zakresie adresów wirtualnych.
Ustawia prawa dostępu (odczyt/zapis) do zmapowanej pamięci dla poszczególnych urządzeń, sterując też dostępem peer-to-peer.
Zwraca wymagane wyrównanie (granulację) rozmiaru alokacji; rozmiary muszą być jego wielokrotnością.
Eksportują i importują alokacje jako uchwyty systemu operacyjnego (deskryptor pliku w Linuksie, HANDLE/D3DKMT_HANDLE w Windows), umożliwiając współdzielenie między procesami oraz z API graficznymi.
Oficjalna
Implementacja
Rozmiary muszą być wielokrotnością wartości z cuMemGetAllocationGranularity; CUDA nie mapuje części pojedynczej alokacji fizycznej.
Programista sam odpowiada za kolejność reserve → create → map → setAccess oraz zwolnienie unmap → release → addressFree; błędy prowadzą do wycieków lub błędów dostępu.
Dostęp innego GPU do pamięci wymaga jawnego cuMemSetAccess; bez tego następuje błąd dostępu.
Ewolucja
CUDA 10.2 dodaje cuMemCreate, cuMemAddressReserve, cuMemMap i cuMemSetAccess, rozdzielając rezerwację adresu od alokacji fizycznej.
Oficjalny przewodnik opisuje wzorce użycia: rosnące alokacje, pule pamięci, IPC i selektywny dostęp peer.
Caching allocator PyTorcha zyskuje tryb expandable_segments wykorzystujący VMM do ograniczania fragmentacji przy zmiennych rozmiarach alokacji.
Hiperparametry (konfigurowalne osie)
Wyrównanie rozmiaru pamięci fizycznej wymagane przez urządzenie; rozmiary alokacji muszą być jego wielokrotnością.
Rodzaj uchwytu OS używanego do współdzielenia: deskryptor pliku POSIX (Linux) albo HANDLE / D3DKMT_HANDLE (Windows).
Prawa odczytu/zapisu ustawiane per urządzenie przez cuMemSetAccess, decydujące też o dostępie peer-to-peer.
Wymagania sprzętowe
API sterownika CUDA działa wyłącznie na GPU NVIDIA wspierających zarządzanie pamięcią wirtualną (od CUDA 10.2).