Lokalność NUMA w lokalnej sztucznej inteligencji: dlaczego rozmieszczenie pamięci zmienia tempo zasilania akceleratora

Eva Wong jest Technicznym pisarzem i stałym majsterkowiczem w ZimaSpace. Całe życie geek z pasją do homelabów i oprogramowania open-source, specjalizuje się w tłumaczeniu skomplikowanych koncepcji technicznych na przystępne, praktyczne przewodniki. Eva wierzy, że samodzielne hostowanie powinno być zabawą, a nie czymś onieśmielającym. Poprzez swoje samouczki umożliwia społeczności rozwiewanie tajemnic konfiguracji sprzętu, od budowy pierwszego NAS po opanowanie kontenerów Docker.

Lokalność NUMA zmienia szybkość dostarczania danych do akceleratora, ponieważ wstępne przetwarzanie na hoście i transfery są szybsze, gdy wątki CPU, strony pamięci i urządzenie korzystają z blisko położonej ścieżki.

W domowej stacji roboczej z wieloma gniazdami każdy rdzeń CPU może adresować całą pamięć RAM, ale koszt dostępu nie jest jednolity. GPU lub inny akcelerator jest zwykle podłączony przez główny kompleks PCIe jednego gniazda. Jeśli wstępne przetwarzanie działa na innym węźle, a bufory są tam alokowane, dane mogą przekraczać magistralę między gniazdami, zanim dotrą do urządzenia, co zwiększa rywalizację i zmienność opóźnień.

NUMA sprawia, że odległość od pamięci hosta staje się mierzalna

System NUMA dzieli procesory i pamięć na węzły o różnej odległości dostępu. Linux zwykle alokuje stronę w węźle lokalnym dla procesora, który jako pierwszy wywołał błąd strony. Umiejscowienie wątków podczas ładowania modelu lub przygotowywania danych wejściowych może więc określać, gdzie fizycznie znajdują się duże bufory.

Dokumentacja zasad pamięci NUMA systemu Linux opisuje zasady dotyczące zadań, VMA, pamięci współdzielonej, wiązania, preferowanego węzła i przeplotu. Zwraca również uwagę, że zasady wpływają głównie na strony alokowane po ich zainstalowaniu, dlatego kolejność inicjalizacji ma znaczenie. To rozróżnienie pozostaje istotne w realistycznych warunkach użytkowania domowego.

W przypadku lokalnego wnioskowania ścieżka krytyczna może obejmować tokenizację, dekodowanie obrazów, przygotowywanie tensorów, bufory przypięte oraz transfery do urządzenia. Umieszczenie danych w zdalnym węźle dodaje wąskie gardło po stronie hosta, nawet gdy sam akcelerator zgłasza niewykorzystaną moc obliczeniową. Stan pośredni powinien pozostać widoczny podczas późniejszej diagnostyki i przeglądu.

Topologia PCIe łączy akcelerator z określonymi węzłami CPU

Najkrótsza ścieżka między hostem a urządzeniem zwykle prowadzi przez gniazdo CPU, którego główny kompleks PCIe obsługuje akcelerator. Przypisanie wątków CPU procesu roboczego i zasad alokacji do tego obszaru może zwiększyć przepustowość i zmniejszyć zmienność, zwłaszcza gdy duże dane wejściowe lub częste transfery stale obciążają łącze.

Wytyczne NVIDIA dotyczące NUMA w CUDA zawierają zalecenia NUMA i ostrzegają, że automatyczne równoważenie może w niektórych przypadkach pogorszyć działanie aplikacji GPU. Zalecają sprawdzenie topologii i dostrojenie zasad do rzeczywistego węzła zamiast zakładania, że najszybszy jest węzeł o numerze zero.

Umiejscowienie jest problemem grafowym, a nie regułą mówiącą, że węzeł zero jest najszybszy. Właściwe powiązanie zależy od okablowania płyty głównej, konfiguracji IOMMU, innych urządzeń oraz tego, czy wiele procesów roboczych konkuruje o te same kanały pamięci lub łącza PCIe.

Wiązanie może zaszkodzić, gdy obciążenie korzysta z więcej niż jednego węzła

Ścisłe przypisanie pamięci do jednego węzła może wyczerpać jego przepustowość lub pojemność, podczas gdy inne węzły pozostaną bezczynne. Potok może korzystać z GPU znajdującego się w pobliżu jednego gniazda, a jednocześnie z karty przechwytującej, urządzenia NVMe lub drugiego akceleratora znajdującego się w pobliżu innego. Jedno ustawienie może zoptymalizować transfery, ale spowolnić wstępne przetwarzanie lub dostęp do pamięci masowej.

Projekt GPU affinity firmy NVIDIA przypisuje procesy do rdzeni CPU powiązanych z układami GPU i wskazuje, że prawidłowe przypisanie może stabilizować wydajność. Jego różne tryby pokazują, dlaczego zakresy obejmujące unikatowe rdzenie, ciągłe rdzenie, gniazdo lub NUMA pasują do różnych obciążeń wieloprocesowych.

Granica błędu przebiega między pojedynczym testem jednego urządzenia a jego uogólnieniem na cały serwer. Nie stosuj wiązania bez namysłu w systemach ze zintegrowaną pamięcią, maszynach jednowęzłowych ani potokach obejmujących kilka urządzeń; mierz kompleksowo opóźnienie, przepustowość i rywalizację przy zakładanej współbieżności.

Testuj topologię, a nie tylko akcelerator

Określ węzły CPU, pojemność pamięci, urządzenia PCIe i lokalizację akceleratora. Uruchom to samo obciążenie wnioskowania przy domyślnym rozmieszczeniu, wiązaniu wyłącznie CPU, wiązaniu wyłącznie pamięci oraz dopasowanym wiązaniu CPU i pamięci. Zapisz przepustowość host–urządzenie, rozmieszczenie stron, liczbę tokenów na sekundę i opóźnienie p95.

Jeśli fragmenty modelu pochodzą z sieciowej pamięci masowej, jak w przypadku sieciowej pamięci modeli, oddziel czas odczytu pliku od rozmieszczenia stron i transferu do urządzenia. Rozgrzej te same dane przed każdym uruchomieniem, a następnie powtórz test z docelową liczbą współbieżnych procesów roboczych, aby ujawnić rywalizację o kanały pamięci.

Stosuj wiązanie tylko wtedy, gdy dopasowana topologia poprawia powtarzalne wyniki kompleksowe bez pozbawiania innej usługi zasobów. Jeśli zyski znikają po rozgrzaniu lub odwracają się przy współbieżności, pozostaw rozmieszczenie elastyczne albo odizoluj tylko wątki i bufory krytyczne dla transferu.

Centrum Technologii i Sztucznej Inteligencji

Więcej do przeczytania

Get More Builds Like This

Stay in the Loop

Get updates from Zima - new products, exclusive deals, and real builds from the community.

Stay in the Loop preferences

We respect your inbox. Unsubscribe anytime.