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.
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.
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.
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”
// for each v.x, ensure v.x >= a.x && v.x <= b.x
inline __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.
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 .
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.