Po wydaniu nowej generacji procesorów większość witryn informuje, że silniki i programy do gier muszą być zoptymalizowane pod kątem nowego sprzętu. Nie bardzo rozumiem dlaczego. Procesor zwykle ma architekturę, która określa, jakiego rodzaju zestawu instrukcji używa. Obecnie wszyscy używamy amd_x86_64. Dlaczego jakikolwiek program lub kompilator powinien być aktualizowany, jeśli wszystkie procesory korzystają z tej samej architektury? Na pewno istnieją funkcje W ramach potoku nowego procesora, który optymalizuje wykonanie kodu maszynowego, ale dlaczego sam kod maszynowy musiałby zostać zmieniony, jeśli architektura nie?
39
Odpowiedzi:
Ponieważ różne generacje tej samej architektury mogą mieć różne zestawy instrukcji .
Na przykład, rozszerzenia SIMD Streaming są prawdopodobnie najbardziej znanym zestawem instrukcji x86, ale mimo to, mimo że istnieje tylko jedna architektura x86, istnieje SSE, SSE2, SSE3 i SSE4.
Każda z tych generacji może zawierać nowe instrukcje, które zapewniają szybsze sposoby wykonywania niektórych operacji. Przykładem odpowiednim dla gier może być instrukcja dot produktu.
Jeśli więc silnik gry zostanie skompilowany dla poprzedniej generacji architektury, nie będzie obsługiwał tych nowszych instrukcji. Podobnie może być konieczna optymalizacja silnika pod kątem nowszych instrukcji; Na przykład SSE4 obsługuje instrukcje dot produktu, które działają na danych typu tablica struktur. Optymalizacja, która mogłaby skorzystać z tych nowszych instrukcji, polegałaby na zmianie układu danych na tablicę struktur.
źródło
Odpowiedź Maximusa jest poprawna, chcę tylko podać kolejny fragment historii:
Sam sprzęt zmienia się w sposób, w jaki należy zmienić sposób kodowania, niezależnie od nowo wprowadzonych instrukcji.
Zwiększona lub zmniejszona ilość pamięci podręcznej oznacza, że musisz mniej lub bardziej martwić się o optymalizację pamięci podręcznej / unieważnienie pamięci podręcznej. Więcej pamięci podręcznej oznacza, że przy małych danych można mniej skupić się na upewnieniu się, że dane są ciągłe i nie występują problemy z wydajnością. Mniej pamięci podręcznej oznacza, że może to być problem, a bardzo mała pamięć podręczna oznacza, że w przypadku niektórych dużych struktur danych nie będzie to miało żadnego znaczenia.
Nowe poziomy pamięci podręcznej oznaczają, że musisz przemyśleć, w jaki sposób organizujesz jeszcze większe zestawy danych (L1, L2, L3 vs L4).
Więcej rdzeni oznacza, że musisz pomyśleć o tym, jak zamierzasz tworzyć aplikacje wielowątkowe i jak Twoja aplikacja skaluje się w środowisku wieloprocesowym.
Szybsze zegary oznaczają, że musisz zacząć myśleć o opóźnieniu pamięci bardziej niż o obliczeniach procesora jako wąskim gardle twojego systemu.
Liczba układów FPU w systemie może już nie odpowiadać liczbie liczb całkowitych ALU na rdzeń (AMD miał / ma takie architektury).
Liczba cykli zegara potrzebnych do obliczenia operacji zmniejszyła się lub wzrosła.
Zmieniła się liczba dostępnych rejestrów.
Wszystko to ma bardzo realny wpływ na wydajność programów, które przyjęły założenia dotyczące architektury bazowej w poprzednim sprzęcie z tym samym ISA, zarówno pozytywnym, jak i negatywnym.
źródło
pdep
Trwa 1 cykl na Intel, ale 6 na Ryzen, więc może nie chcieć używać go na Ryzen.c[i] = a[i] OP b[i]
(tj. 2 obciążenia i 1 pamięć na operację), więc czasy są zdominowane przez przepustowość pamięci z powodu bardzo niskiej intensywności obliczeniowej. Rozmiar tablicy nie jest pokazywany, więc IDK, jeśli pasuje do L1D. (gcc4.9 -Ofast
najprawdopodobniej automatycznie wektoryzują te pętle, więc nawet nie mierzysz kosztów normalnych operacji skalarnych jako części złożonego kodu liczb całkowitych). Pierwszy wiersz tej strony jest WAŻNY: Przydatne informacje zwrotne ujawniły, że niektóre z tych środków mają poważne wady. Nadchodzi ważna aktualizacja .Nawet poza poważnymi zmianami, takimi jak obsługa nowych instrukcji, producenci mikroprocesorów stale modyfikują swoje projekty, aby poprawić wydajność, a każdy nowy projekt może mieć inną wydajność względną dla każdej instrukcji lub techniki. Być może napisałeś starannie zoptymalizowany kod bez rozgałęzień dla Modelu X, ale Model Y ma ulepszoną funkcję przewidywania rozgałęzień, która zmniejsza karę za nieprzewidywalność dla wersji bez rozgałęzień kodu (co również uwalnia rejestr do użycia w innym miejscu) . Być może Model Y obsługuje większą równoległość pewnej instrukcji o dużym opóźnieniu, tak że teraz rozwinięta pętla tej instrukcji zapewnia lepszą przepustowość, podczas gdy na Modelu X krótsza sekwencja była lepsza.
Każdy problem można rozwiązać na wiele sposobów, a każdy program to zbiór kompromisów i alokacji zasobów, od punktu optymalizacji. Nawet niewielkie zmiany w dostępności tych zasobów lub koszcie danego fragmentu kodu w odniesieniu do tych zasobów mogą mieć efekt kaskadowy, który daje znaczną przewagę wydajności dla jednego fragmentu kodu. Nawet jeśli ulepszony układ ma „więcej wszystkiego”, o ile więcej z każdej rzeczy może zmienić równowagę.
źródło