Ile asemblacji jest naprawdę używanych we współczesnym kodzie gry? [Zamknięte]
21
Jak często używa się asemblera we współczesnym kodzie gry?
Zwłaszcza na platformach, które mają już dobre kompilatory C ++, takie jak x86, PPC lub ARM - ponieważ zakładam, że gry na systemach wbudowanych często korzystają z asemblera.
C ++ nie kompiluje się w asemblerze - kompiluje się w kod maszynowy. Język asemblera to sposób bezpośredniego określenia dokładnie, jaki kod maszynowy chcesz wygenerować.
Kylotan,
6
C ++ nie jest (ogólnie) właściwie kompilowany do asemblera, jest kompilowany bezpośrednio do kodu maszynowego. Pytanie prawdopodobnie dotyczy tego, ile ręcznie napisanych zestawów jest połączonych z projektem lub napisanych jako zestaw wbudowany.
1
Niezależnie od tego nie sądzę, aby na to pytanie była praktyczna i przydatna odpowiedź. Zasadniczo zależy to od podobnych czynników, z których wiele jest subiektywnych (tj. Opinii autorów kodu).
1
W dzisiejszych czasach nie jest tak ważne pisanie asemblera, z pewnymi wyjątkami, takimi jak programowanie SPU, ale możliwość czytania jest ważna przy analizie zrzutów
awaryjnych
4
@ Legion - możesz spowodować, że kompilator / IDE wyemituje zestaw, ale to nie znaczy, że kompilator tworzy zestaw jako część normalnego procesu kompilacji. Nie jest to konieczne, a zatem większość tego nie robi.
Odpowiedzi:
29
Odpowiedź zależy trochę od tego, co rozumiesz przez „grę” i od „używanego”. Zakładam, że „używany” oznacza „napisany w trakcie konkretnego projektu gry”.
Z mojego doświadczenia i anegdotycznych danych od osób, z którymi rozmawiałem:
w grach przeglądarkowych? Żaden.
w typowych grach komputerowych? Żaden. (Ale możesz zobaczyć niektóre w bibliotekach niskiego poziomu).
w grach na iOS i Androida? Żaden.
Gry na PC i konsole „AAA”? Może trochę, może 0,05% podstawy kodu. (Trochę więcej w bibliotekach.)
Znajomość języka asemblera nie jest wymagana do pracy w branży gier, ale w zależności od rodzaju tworzonych gier może być korzystna.
Argumentowano, że kompilator lepiej radzi sobie z optymalizacją kodu C niż człowiek z ręcznie napisanym zestawem. Zwykle to prawda, czasem fałsz. Ale obecnie połączenie stale rosnącej złożoności procesora i potrzeby skalowania „poza” (tj. Oddzielnych procesorów) oznacza, że wysiłki związane z optymalizacją są zwykle podejmowane gdzie indziej.
W ostatnich latach jedynym razem, gdy widziałem asembler w kodzie gry, były __asm int 3stwierdzenia wymuszające punkty przerwania, a moim jedynym osobistym zastosowaniem asemblera było spojrzenie na dezasemblację funkcji do diagnozowania niezwykłych błędów awarii.
@Legion, ludzie zwykle piszą kod SSE za pomocą wewnętrznych funkcji lub bibliotek matematycznych, które zawierają elementy SSE, lub w specjalnym mini-języku zaprojektowanym specjalnie do kompilacji do SSE, takim jak ispc . Bezpośrednie pisanie asemblera wciąż jest dość rzadkie.
Nathan Reed,
1
Odnośnie gier na iOS: O ile dobrze pamiętam, biblioteka 3D / Math Oolong używała wbudowanego zestawu ARM. Nie jest to już potrzebne, ponieważ Apple wydało platformę Accelerate.
Nicolas Miari,
Uzgodnione z Nathanem - SSE i podobne optymalizacje specyficzne dla instrukcji zwykle istnieją w bibliotekach (ponieważ są to zwykle jedyne miejsca, w których łączna uzyskana korzyść jest warta włożonego wysiłku).
// for each v.x, ensure v.x >= a.x && v.x <= b.xinline __m128 ClampSIMD(const __m128 &v,const __m128 & a,const __m128 & b ){return _mm_max_ps( a, _mm_min_ps( v, b ));}
W takich funkcjach wciąż myślę o kategoriach konkretnych instrukcjach maszyny , ale mam wygodę pisania ich w C, aby nie musiałem martwić się o rejestrowanie kolorów i harmonogramów oraz ładowanie operacji i innych nudnych szczegółów.
Nadal musisz zdawać sobie sprawę z tego, jakie instrukcje obsługuje procesor, szczególnie dlatego, że współczesne kompilatory źle sobie radzą z wektoryzacją kodu, w porównaniu do tego, jak dobrze inteligentny człowiek potrafi to zrobić. Czasami subtelne szczegóły dotyczące sposobu organizacji kodu mogą mieć ogromny wpływ na wydajność , które nie są oczywiste bez zrozumienia, co robi maszyna.
Chociaż możemy nie kodować w asemblerze, wciąż dużo debugujemy w asemblerze. Optymalizacja kompilatorów agresywnie reorganizuje kod w sposób, który nie jest w stanie nadążyć za debuggerami, więc często przy debugowaniu kompilacji w „trybie wydania” najlepiej jest otworzyć deasembler i prześledzić kod w ten sposób. To przemówienie GDC na temat „Debugowania sądowego” awarii ilustruje wiele powodów debugowania na tym poziomie.
+1 po prostu dlatego, że Crashworks jest dobrze znany na SO jako „ten facet, który pisze naprawdę zoptymalizowany kod do gier” - jeśli ktoś wie na ten temat, to on.
BlueRaja - Danny Pflughoeft
@ BlueRaja-DannyPflughoeft „Dobrze znany”? Pochlebia mi! =) Zabawnym zbiegiem okoliczności, w świetle komentarzy Nathana Reeda, jest to, że nauczyłem się wielu z moich umiejętności optymalizacji na niskim poziomie w Naughty Dog.
Crashworks,
Gdzie indziej słyszałem też o znaczeniu assemblera w debugowaniu. Więc się tego nauczę. Dzięki za wgląd i linki.
Legion
7
Problemów, które wymagały wcześniej ręcznego walcowania, jest coraz mniej. To, co „możesz” przyśpieszyć, tracisz czytelność i zdolność do debugowania. Powinno to być zrobione tylko jako jeden z ostatnich kroków optymalizacji sekcji kodu, ponieważ w większości przypadków problemy z szybkością nie są czymś, czego nie można poprawić dzięki asemblerowi. Obecnie procesory stały się znacznie szybsze, a prędkości pamięci nie. Często ważniejsze jest kontrolowanie przepływu danych przez procesor niż cokolwiek innego.
Współczesne kompilatory mają również trudności z optymalizacją kodu asemblera, ponieważ mają do czynienia z rejestrami, których dotknąłeś, i zwykle nie mogą ponownie zamówić instrukcji w ręcznie spreparowanym kodzie. Aby zmniejszyć potrzebę montażu, istnieją teraz również wewnętrzne elementy które pomagają uzyskać dostęp do koncepcji niskiego poziomu, ale w sposób przyjazny dla kompilatora i pozwalający im pracować z tobą, a nie przeciwko.
Biorąc to pod uwagę, SPU na PS3 jest jednym z obszarów, w którym ludzie nadal muszą korzystać z asemblera, aby uzyskać jak najwięcej z procesora, z ręcznym potokowaniem instrukcji, na przykład, jak wyjaśniono tutaj .
Nawet na PS3 ludzie zwykle nie do końca programują w goły sposób. Istnieje narzędzie, które pozwala pisać kod w składni podobnej do asemblera, w którym określasz instrukcje maszynowe, ale dokonuje dla ciebie alokacji rejestrów, planowania instrukcji i potokowania w pętli. Cóż, może Naughty Dog naprawdę robi to wszystko ręcznie, ale nawet większość programistów PS3 SPU nie robi tego. :)
Nathan Reed,
1
@NathanReed W dniach PS2 ręczne tworzenie potoków było właściwie częścią wywiadu programistycznego Naughty Dog.
Crashworks,
-1
Faktem jest, że żyjemy w świecie wieloplatformowym, a niektóre elementy naszego kodu gry muszą być dostosowane do platformy lokalnej - no cóż, niekoniecznie, ale są korzyści, jeśli skorzystamy z lokalnego sprzętu!
Tu nie chodzi o gry ani logikę gry, chodzi o lokalizację sprzętu dla optymalnej wydajności kodu, na którym opiera się logika gry, możemy rzeczywiście zawijać sekcje kodu, na przykład za pomocą makr, tak aby istniał jeden kod źródłowy, który działa dobrze na platforma, na której został zbudowany.
Odpowiedzi:
Odpowiedź zależy trochę od tego, co rozumiesz przez „grę” i od „używanego”. Zakładam, że „używany” oznacza „napisany w trakcie konkretnego projektu gry”.
Z mojego doświadczenia i anegdotycznych danych od osób, z którymi rozmawiałem:
Znajomość języka asemblera nie jest wymagana do pracy w branży gier, ale w zależności od rodzaju tworzonych gier może być korzystna.
Argumentowano, że kompilator lepiej radzi sobie z optymalizacją kodu C niż człowiek z ręcznie napisanym zestawem. Zwykle to prawda, czasem fałsz. Ale obecnie połączenie stale rosnącej złożoności procesora i potrzeby skalowania „poza” (tj. Oddzielnych procesorów) oznacza, że wysiłki związane z optymalizacją są zwykle podejmowane gdzie indziej.
W ostatnich latach jedynym razem, gdy widziałem asembler w kodzie gry, były
__asm int 3
stwierdzenia wymuszające punkty przerwania, a moim jedynym osobistym zastosowaniem asemblera było spojrzenie na dezasemblację funkcji do diagnozowania niezwykłych błędów awarii.źródło
Większość wysokowydajnego kodu we współczesnych grach konsolowych jest napisana przy użyciu pewnego rodzaju pośrednika między asemblerem i wewnętrznym kompilatorem C ++: kompilatora . Te konstrukcje wyglądają i analizują jak funkcje C ++, ale w rzeczywistości są tłumaczone na instrukcje dla jednej maszyny . Na przykład, mój „zacisk każdą wartość wektora V ma być> = a i <= b”
W takich funkcjach wciąż myślę o kategoriach konkretnych instrukcjach maszyny , ale mam wygodę pisania ich w C, aby nie musiałem martwić się o rejestrowanie kolorów i harmonogramów oraz ładowanie operacji i innych nudnych szczegółów.
Nadal musisz zdawać sobie sprawę z tego, jakie instrukcje obsługuje procesor, szczególnie dlatego, że współczesne kompilatory źle sobie radzą z wektoryzacją kodu, w porównaniu do tego, jak dobrze inteligentny człowiek potrafi to zrobić. Czasami subtelne szczegóły dotyczące sposobu organizacji kodu mogą mieć ogromny wpływ na wydajność , które nie są oczywiste bez zrozumienia, co robi maszyna.
Chociaż możemy nie kodować w asemblerze, wciąż dużo debugujemy w asemblerze. Optymalizacja kompilatorów agresywnie reorganizuje kod w sposób, który nie jest w stanie nadążyć za debuggerami, więc często przy debugowaniu kompilacji w „trybie wydania” najlepiej jest otworzyć deasembler i prześledzić kod w ten sposób. To przemówienie GDC na temat „Debugowania sądowego” awarii ilustruje wiele powodów debugowania na tym poziomie.
źródło
Problemów, które wymagały wcześniej ręcznego walcowania, jest coraz mniej. To, co „możesz” przyśpieszyć, tracisz czytelność i zdolność do debugowania. Powinno to być zrobione tylko jako jeden z ostatnich kroków optymalizacji sekcji kodu, ponieważ w większości przypadków problemy z szybkością nie są czymś, czego nie można poprawić dzięki asemblerowi. Obecnie procesory stały się znacznie szybsze, a prędkości pamięci nie. Często ważniejsze jest kontrolowanie przepływu danych przez procesor niż cokolwiek innego.
Współczesne kompilatory mają również trudności z optymalizacją kodu asemblera, ponieważ mają do czynienia z rejestrami, których dotknąłeś, i zwykle nie mogą ponownie zamówić instrukcji w ręcznie spreparowanym kodzie. Aby zmniejszyć potrzebę montażu, istnieją teraz również wewnętrzne elementy które pomagają uzyskać dostęp do koncepcji niskiego poziomu, ale w sposób przyjazny dla kompilatora i pozwalający im pracować z tobą, a nie przeciwko.
Biorąc to pod uwagę, SPU na PS3 jest jednym z obszarów, w którym ludzie nadal muszą korzystać z asemblera, aby uzyskać jak najwięcej z procesora, z ręcznym potokowaniem instrukcji, na przykład, jak wyjaśniono tutaj .
źródło
Faktem jest, że żyjemy w świecie wieloplatformowym, a niektóre elementy naszego kodu gry muszą być dostosowane do platformy lokalnej - no cóż, niekoniecznie, ale są korzyści, jeśli skorzystamy z lokalnego sprzętu!
Tu nie chodzi o gry ani logikę gry, chodzi o lokalizację sprzętu dla optymalnej wydajności kodu, na którym opiera się logika gry, możemy rzeczywiście zawijać sekcje kodu, na przykład za pomocą makr, tak aby istniał jeden kod źródłowy, który działa dobrze na platforma, na której został zbudowany.
źródło