Tam, gdzie pracowałem, zawsze używamy wielu poziomów profilowania; jeśli zauważysz problem, po prostu przesuń się nieco dalej w dół listy, aż zorientujesz się, co się dzieje:
- „Human profiler”, czyli po prostu zagraj w grę ; czy czasami wydaje się powolny lub „zaczep”? Zauważyłeś gwałtowne animacje? (Jako programista pamiętaj, że będziesz bardziej wrażliwy na niektóre problemy z wydajnością i nieświadomy innych. Odpowiednio zaplanuj dodatkowe testy).
- Włącz wyświetlacz FPS , który jest przesuwanym 5-sekundowym średnim FPS. Bardzo małe koszty ogólne do obliczenia i wyświetlenia.
- Włącz paski profilu , które są tylko serią quadów (kolory ROYGBIV), które reprezentują różne części ramki (np. Vblank, preframe, update, collision, render, postframe) za pomocą prostego timera „stopera” wokół każdej sekcji kodu . Aby podkreślić to, czego chcemy, ustawiliśmy pasek o szerokości jednego ekranu, aby był reprezentatywny dla ramki docelowej 60 Hz, więc naprawdę łatwo jest sprawdzić, czy np. Masz 50% mniej budżetu (tylko pół słupka), czy 50% więcej ( pasek owija się i staje się półtora paska). Łatwo jest również stwierdzić, co ogólnie zjada większość ramki: czerwony = renderowanie, żółty = aktualizacja itp.
- Zbuduj specjalną oprzyrządowaną kompilację, która wstawia „stoper” jak kod wokół każdej funkcji. (Pamiętaj, że możesz przy tym zrobić ogromne uderzenie wydajności, dcache i icache, więc jest to zdecydowanie ingerujące. Ale jeśli brakuje odpowiedniego profilera próbkowania lub przyzwoitej obsługi procesora, jest to dopuszczalna opcja. Możesz także być sprytny o nagrywaniu minimum danych o wejściu / wyjściu funkcji i późniejszej przebudowie śladów wywołań.) Kiedy budowaliśmy nasze, naśladowaliśmy wiele formatu wyjściowego gprof .
- Co najlepsze, uruchom profilowanie próbkowania ; VTune i CodeAnalyst są dostępne dla x86 i x64, masz różne środowiska symulacji lub emulacji, które mogą dawać ci dane tutaj.
(Zabawna historia z ubiegłorocznego GDC programisty grafiki, który zrobił sobie cztery zdjęcia - szczęśliwego, obojętnego, zirytowanego i wściekłego - i pokazał odpowiednie zdjęcie w rogu wewnętrznych kompilacji na podstawie liczby klatek na sekundę. twórcy treści szybko nauczyli się nie włączać skomplikowanych shaderów dla wszystkich swoich obiektów i środowisk: rozgniewałyby programistę. Zobacz moc sprzężenia zwrotnego).
Pamiętaj, że możesz również robić zabawne rzeczy, takie jak ciągłe wykresy „pasków profilu”, dzięki czemu możesz zobaczyć wzorce pików („tracimy ramkę co 7 klatek”) lub podobne.
Aby odpowiedzieć bezpośrednio na twoje pytanie: z mojego doświadczenia, podczas gdy kuszące (i często satysfakcjonujące - zwykle czegoś się uczę), przepisanie pojedynczych funkcji / modułów w celu zoptymalizowania liczby instrukcji lub wydajności icache lub dcache, i faktycznie musimy to zrobić czasami, gdy mamy szczególnie wstrętny problem z wydajnością, zdecydowana większość problemów z wydajnością, z którymi regularnie się borykamy, sprowadza się do projektowania . Na przykład:
- Czy powinniśmy buforować w pamięci RAM lub ponownie ładować z dysku ramki animacji stanu „ataku” odtwarzacza? Co powiesz na każdego wroga? Nie mamy pamięci RAM, aby wykonać je wszystkie, ale obciążenia dysków są drogie! Możesz zobaczyć zaczep, jeśli pojawi się 5 lub 6 różnych wrogów naraz! (Dobra, a co powiesz na oszałamiające tarło?)
- Czy wykonujemy jeden rodzaj operacji na wszystkich cząsteczkach, czy wszystkie operacje na pojedynczej cząsteczce? (Jest to kompromis icache / dcache, a odpowiedź nie zawsze jest jasna.) Co powiesz na rozebranie wszystkich cząstek i przechowywanie razem pozycji (słynna „struktura tablic”) w porównaniu do przechowywania wszystkich danych cząstek w jednym miejscu („ tablica struktur ”).
Słyszysz go, dopóki nie stanie się nieprzyjemny na kursach informatycznych na uniwersytecie, ale: tak naprawdę chodzi o struktury danych i algorytmy. Poświęcenie czasu na projektowanie algorytmów i przepływów danych zapewni ci więcej korzyści. (Upewnij się, że zapoznałeś się z doskonałymi slajdami z zakresu programowania obiektowego przedstawionymi przez pracowników Sony Developer Services, aby uzyskać wgląd tutaj.) To nie „wydaje się” jak optymalizacja; to głównie czas spędzany z tablicą lub narzędziem UML lub tworzeniem wielu prototypów, zamiast przyspieszania bieżącego kodu. Ale ogólnie jest o wiele bardziej opłacalne.
I jeszcze jedna przydatna heurystyka: jeśli jesteś blisko „rdzenia” silnika, warto zoptymalizować (np. Wektoryzację mnożenia macierzy!) Dodatkowego eksperymentu i eksperymentów. Im dalej od rdzenia, tym mniej powinieneś się tym przejmować, chyba że jedno z narzędzi profilujących mówi inaczej.
Pamiętaj jednak także o „przedwczesnej pesymizacji”. Chociaż nie ma potrzeby wybierać się na każdy wiersz kodu, istnieje uzasadnienie dla zrozumienia, że faktycznie pracujesz nad grą, która ma wpływ na wydajność w czasie rzeczywistym.
Podczas gdy wszyscy mówią ci, aby mierzyć i optymalizować hotspoty, ta technika nie pokazuje wydajności utraconej w ukrytych miejscach. Na przykład, jeśli każda operacja „+” w kodzie zajmie dwa razy więcej czasu, niż powinna, nie pojawi się jako hot-spot, a zatem nigdy go nie zoptymalizujesz, a nawet nie zauważysz, ponieważ jest on używany w całym miejsce może kosztować dużo wydajności. Byłbyś zaskoczony, jak wiele z tych cykli ucieka, nie będąc nigdy wykrytym. Bądź więc świadom tego, co robisz.
Poza tym zwykle profiluję się regularnie, aby dowiedzieć się, co tam jest i ile czasu pozostało na klatkę. Dla mnie czas na klatkę jest najbardziej logiczny, ponieważ mówi mi bezpośrednio, gdzie jestem, z celami klatek na sekundę. Spróbuj także dowiedzieć się, gdzie są szczyty i co je powoduje - wolę stabilną szybkość klatek niż wysoką szybkość klatek z kolcami.
źródło
Gdy gra będzie gotowa do wydania (wersja ostateczna lub beta) lub będzie zauważalnie wolna, to prawdopodobnie najlepszy czas na profilowanie aplikacji. Oczywiście zawsze możesz uruchomić profiler w dowolnym momencie; ale tak, przedwczesna optymalizacja jest źródłem wszelkiego zła. Nieuzasadniona optymalizacja również; potrzebujesz rzeczywistych danych, aby pokazać, że jakiś kod działa wolno, zanim zaczniesz go „optymalizować”. Profiler robi to za Ciebie.
Jeśli nie wiesz o profilerze, naucz się go! Oto dobry post na blogu pokazujący przydatność profilera.
W przeciwnym razie, jeśli Twoja mała gra działa przy 200 FPS, mimo że ma nieefektywny algorytm, czy naprawdę masz powód do optymalizacji? Powinieneś mieć dobry pomysł na specyfikację komputera docelowego i upewnić się, że gra działa dobrze na tym komputerze, ale poza tym wszystko (prawdopodobnie) to zmarnowany czas, który można lepiej poświęcić na kodowanie lub dopracowywanie gry.
źródło
Uważam, że przydatne jest budowanie profilowania. Nawet jeśli nie aktywnie optymalizujesz, dobrze jest mieć pomysł na to, co ogranicza Twoją wydajność w danym momencie. Wiele gier ma nakładany HUD, który wyświetla prosty wykres graficzny (zwykle tylko kolorowy pasek) pokazujący, jak długo poszczególne części pętli gry zajmują każdą klatkę.
Byłoby złym pomysłem pozostawienie analizy i optymalizacji wydajności zbyt późno na późnym etapie. Jeśli już zbudowałeś grę i masz 200% więcej niż budżet procesora i nie możesz tego znaleźć dzięki optymalizacji, to masz problemy.
Podczas pisania musisz wiedzieć, jakie są budżety na grafikę, fizykę itp. Nie możesz tego zrobić, jeśli nie masz pojęcia, jaka będzie twoja wydajność, i nie możesz zgadywać, nie wiedząc, jaka jest twoja wydajność i jaki może być zastój.
Więc buduj statystyki wydajności od pierwszego dnia.
Co do tego, kiedy radzić sobie z różnymi rzeczami - prawdopodobnie lepiej nie pozostawiać tego za późno, aby nie trzeba było refaktoryzować połowy silnika. Z drugiej strony, nie skupiaj się zbytnio na optymalizacji rzeczy, aby wycisnąć każdy cykl, jeśli uważasz, że możesz zmienić algorytm całkowicie jutro lub jeśli nie przeszedłeś przez to prawdziwych danych gry.
Zrywaj wiszące nisko owoce, od czasu do czasu radz sobie z dużymi rzeczami i wszystko powinno być w porządku.
źródło
Jeśli spojrzy na cytat Knutha w jego kontekście, wyjaśnia dalej, że powinniśmy optymalizować, ale za pomocą narzędzi, takich jak profiler.
Powinieneś stale profilować i profilować pamięć swojej aplikacji po ułożeniu bardzo podstawowej architektury.
Profilowanie nie tylko pomoże zwiększyć prędkość, ale także pomoże znaleźć błędy. Jeśli twój program nagle drastycznie zmienia prędkość, zwykle dzieje się tak z powodu błędu. Jeśli nie jesteś profilowany, może zostać niezauważony.
Sztuką optymalizacji jest zrobienie tego zgodnie z projektem. Nie czekaj do ostatniej chwili. Upewnij się, że konstrukcja programu zapewnia wydajność, której potrzebujesz, bez naprawdę paskudnych sztuczek w pętli wewnętrznej.
źródło
W moim projekcie zwykle stosuję BARDZO potrzebną optymalizację w moim silniku podstawowym. Na przykład zawsze lubię implementować dobrą solidną implementację SIMD przy użyciu SSE2 i 3DNow! Zapewnia to, że moja matematyka zmiennoprzecinkowa jest zgodna z tym, gdzie chcę. Inną dobrą praktyką jest nawyk optymalizacji dzięki kodowaniu zamiast cofania się. Przez większość czasu te małe praktyki są tak samo czasochłonne, jak to, co pisałeś. Przed zakodowaniem funkcji upewnij się, że znalazłeś najbardziej efektywny sposób, aby to zrobić.
Podsumowując, moim zdaniem, jest trudniej, aby twój kod był bardziej wydajny po tym, jak już jest do bani.
źródło
Powiedziałbym, że najłatwiejszym sposobem jest użycie zdrowego rozsądku - jeśli coś wygląda na to, że działa wolno, spójrz na to. Sprawdź, czy jest to wąskie gardło.
Skorzystaj z narzędzia do profilowania, aby zobaczyć, jakie funkcje prędkości biorą i jak często są wywoływane.
Absolutnie nie ma sensu optymalizować lub spędzać czasu próbując zoptymalizować coś, czego nie potrzebuje.
źródło
Jeśli kod działa wolno, uruchom profiler i zobacz, co dokładnie powoduje jego wolniejsze działanie. Lub możesz być proaktywny i już mieć profiler, zanim zaczniesz zauważać problemy z wydajnością.
Będziesz chciał zoptymalizować, gdy liczba klatek na sekundę spadnie do punktu, w którym gra zacznie cierpieć. Najbardziej prawdopodobnym winowajcą będzie nadmierne zużycie procesora (100%).
źródło
Powinieneś optymalizować kod ... tak często, jak potrzebujesz.
To, co zrobiłem w przeszłości, to ciągłe uruchamianie gry z włączonym profilowaniem (przynajmniej licznik klatek na ekranie przez cały czas). Jeśli gra staje się wolniejsza (na przykład poniżej docelowej liczby klatek na maszynie z minimalną specyfikacją), włącz profiler i sprawdź, czy pojawią się jakieś gorące punkty.
Czasami to nie jest kod. Wiele problemów, które napotkałem w przeszłości, dotyczyły procesorów GPU (oczywiście, było to na iPhonie). Problemy z wypełnianiem, zbyt wiele wywołań do rysowania, niewystarczająca geometria, nieefektywne moduły cieniujące ...
Poza nieefektywnymi algorytmami trudnych problemów (np. Wyszukiwanie ścieżek, fizyka) bardzo rzadko napotykałem problemy, w których przyczyną był sam kod. A te trudne problemy powinny być rzeczami, które poświęcasz dużo wysiłku na poprawne działanie algorytmu i nie martwisz się o mniejsze rzeczy.
źródło
Dla mnie najlepiej śledzić dobrze przygotowany model danych. I optymalizacja - przed głównym krokiem naprzód. Mam na myśli, zanim zacznę wdrażać coś nowego. Innym powodem optymalizacji jest to, że kiedy tracę kontrolę nad zasobami, aplikacja potrzebuje dużo obciążenia procesora / GPU lub pamięci i nie wiem dlaczego :) lub to za dużo.
źródło