W przypadku programów związanych z pamięcią nie zawsze jest szybsze do użycia wielu wątków, powiedzmy taką samą liczbę jak rdzeni, ponieważ wątki mogą konkurować o kanałach pamięci. Zwykle na maszynie do dwóch gniazdo mniej gwintów jest lepszy, ale musimy ustawić zasady powinowactwa, które dystrybuuje nici w różnych gniazdach, aby zmaksymalizować przepustowość pamięci.

Intel OpenMP twierdzi, że KMP_Affinity = rozproszenie jest osiągnięcie tego celu, wartość przeciwna "Compact" jest umieszczenie wątków jak najbliżej. Użyłem ICC do budowy programu strumienia do benchmarkingu, a twierdzenie to jest łatwe weryfikowane na maszynach Intel. A jeśli komp_proc_bind jest ustawiony, Native OpenMP Env Vars, takich jak Op_places i OMP_Proc_bind są ignorowane. Otrzymasz takie ostrzeżenie:

        OMP: Warning #181: OMP_PROC_BIND: ignored because KMP_AFFINITY has been defined

Jednak benchmark na najnowszej maszynie AMD EPYC, który otrzymałem pokazuje naprawdę dziwaczne wyniki. KMP_Affinity = rozproszenie zapewnia najwolniejszą przepustowość pamięci możliwe . Wydaje się, że to ustawienie robi dokładnie odwrotnie na maszynach AMD: umieszczanie gwintów jak najbliżej, aby nawet pamięć podręczna L3 na każdym węźle NUMA nie jest nawet w pełni wykorzystana. A jeśli wyraźnie ustawię komp_proc_bind = rozprzestrzenił się, jest ignorowany przez Intel OpenMP, ponieważ mówi się powyżej ostrzeżenie.

Maszyna AMD ma dwie gniazda, 64 fizyczne rdzenie na gniazdo. Przetestowałem przy użyciu 128, 64 i 32 wątków i chcę, aby zostały rozłożone w całym systemie. Korzystanie z omp_proc_bind = rozprzestrzenianie się, strumień daje mi odpowiednio prędkość triady 225, 290 i 300 GB / s. Ale gdy ustawiłem KMP_Affinity = rozproszenie, nawet gdy omp_proc_bind = spread jest nadal obecny, strumienie dają 264, 144 i 72 GB / s.

Zauważ, że dla 128 wątków na 128 rdzeni, ustawienie KMP_Affinity = rozproszenie daje lepszą wydajność, nawet sugeruje, że w rzeczywistości wszystkie wątki są umieszczone jak najbliżej, ale w ogóle nie rozpraszają.

Podsumowując, KMP_Affinity = rozproszony wyświetla się całkowicie naprzeciwko ( w zachowaniu zachowania ) na maszynach AMD, a nawet nadpisuje natywne środowisko OpenMP niezależnie od marki CPU. Cała sytuacja brzmi nieco rybacki, ponieważ jest znany, że ICC wykrywa markę CPU i wykorzystuje dyspozytora CPU w MKL, aby uruchomić wolniejszy kod na maszynach innych niż Intel. Dlaczego więc ICC nie może po prostu wyłączyć KMP_Affinity i przywrócić OMP_Proc_Bind, jeśli wykryje CPU nie Intel?

Czy to jest znany problem dla kogoś? Lub ktoś może potwierdzić moje odkrycia?

Aby dać więcej kontekstu, jestem deweloperem komercyjnego programu Dynamics Computational Fluid Dynamics i niestety łączymy nasz program za pomocą biblioteki ICC OpenMP i KMP_Afty = rozproszenie jest ustawiony domyślnie, ponieważ w CFD musimy rozwiązać duże rzadkie systemy liniowe, a ta część jest niezwykle związany z pamięcią. Odkryłem, że z ustawieniem KMP_Affinity = rozproszenie, nasz program staje się 4x wolniejszy (przy użyciu 32 wątków) niż rzeczywista prędkość Program może osiągnąć na maszynie AMD.

Aktualizacja:

Teraz używając HWLOC-PS Mogę potwierdzić, że KMP_Affinity = rozproszenie faktycznie robi "Compact" na moim maszynie AMD Threatripper 3. Dołączyłem wynik LSTOPO. Prowadzę mój program CFD (zbudowany przez ICC2017) z 16 wątkami. OPM_PROC_Bind = Spread może umieścić jeden wątek w każdym CCX, aby pamięć podręczna L3 była w pełni wykorzystana. HWLOC-PS -L -T daje:

enter image description here

Oznaczając KMP_Affinity = rozproszony, mam

enter image description here

Spróbuję najnowszego uruchomienia Runtime ICC / Clang OpenMP i zobacz, jak działa.

enter image description here

3
AeroD 18 październik 2020, 06:52

1 odpowiedź

Najlepsza odpowiedź

tl; dr : nie używaj KMP_AFFINITY. Nie jest przenośny. Preferuj OMP_PROC_BIND (nie można go używać z KMP_AFFINITY w tym samym czasie). Możesz je wymieszać z OMP_PLACES, aby ręcznie wiązać nici do rdzeni. Co więcej, numactl należy użyć do sterowania wiązaniem kanału pamięci lub więcej efektów NUMA.

Długa odpowiedź :

wiązanie wątków : OMP_PLACES może być użyte do związania każdego wątku do określonego rdzenia (zmniejszając przełączniki kontekstowe i problemy z NUMA). OMP_PROC_BIND i KMP_AFFINITY powinny teoretycznie zrobić to poprawnie, ale w praktyce nie robią tego w niektórych systemach. Należy pamiętać, że OMP_PROC_BIND i KMP_AFFINITY są wyłączną opcją: powinny one być używane razem (OMP_PROC_BIND to nowa przenośna wymiana starszego {x6}} środowiska zmienna). Jako topologia zmiany rdzenia z jednej maszyny do drugiej można użyć narzędzia hwloc, aby uzyskać listę identyfikatorów PU wymaganych przez OMP_PLACES. W szczególności hwloc-calc, aby uzyskać listę i {{x10}}, aby sprawdzić topologię procesora. Wszystkie wątki powinny być związane oddzielnie, aby żaden ruch nie jest możliwy. Możesz sprawdzić wiązanie wątków za pomocą {{x11}}.

Efekty NUMA : Procesory AMD są zbudowane przez montaż wielu CCX połączony ze sobą z połączeniem o wysokiej przepustowości (tkanina nieskończoności AMD). Z tego powodu procesory AMD są Systemy NUMA . Jeśli nie uwzględniono, efekty NUMA może spowodować znaczny spadek wydajności. Narzędzie numactl jest przeznaczone do sterowania / łagodzenia Efektów NUMA: Procesy mogą być związane z kanałami pamięci za pomocą opcji {X1}}, a polityka alokacji pamięci można ustawić na --interleave (lub --interleave (lub --interleave (lub {{x3) }} Jeśli proces jest świadomy NUMA). Idealnie, procesy / wątki powinny działać tylko na danych przydzielonych i pierworą dotkniętą w lokalnych kanałach pamięci. Jeśli chcesz przetestować konfigurację na danym CCX, możesz odtworzyć za pomocą --physcpubind i --cpunodebind.

Domyślam się, że wykonanie Intel / Clangmtime nie wykonywać dobrej wiązania wątku, gdy jest ustawiony KMP_AFFINITY=scatter. Złe ustawienia użytkownika / administratora). Prawdopodobnie z powodu CCX (ponieważ procesory głównego nurtu zawierającego wiele węzłów NUMA były dość rzadkie).
Na procesorach AMD wątki uzyskujące pamięć innego CCX zazwyczaj płacą dodatkowy znaczący koszt z powodu danych przenoszących przez (dość-wolno) tkanina nieskończoności InterConnect i prawdopodobnie ze względu na jego nasycenie jak również jeden z kanałów pamięci. Radzę nie ufać automatycznego wiązania wątku Runtime OpenMP (użyj {x1}}), aby raczej wykonać powiązania wątku / pamięci ręcznie, a następnie w razie potrzeby zgłaszać błędy.

Oto przykład wykonanej linii poleceń, aby uruchomić aplikację: numactl --localalloc OMP_PROC_BIND=TRUE OMP_PLACES="{0},{1},{2},{3},{4},{5},{6},{7}" ./app

PS : Uważaj na identyfikatory PU / Core i Logiczne / fizyczne IDS.

3
user3666197 20 październik 2020, 03:49