W ciągu ostatniego roku rozwoju mojego silnika szachowego (www.chessbin.com) przez większość czasu optymalizowano mój kod, aby umożliwić lepsze i szybsze wyszukiwanie ruchów. Przez ten czas nauczyłem się kilku sztuczek, którymi chciałbym się z wami podzielić.
wydajność
pomiarowe Zasadniczo można poprawić osiągi na dwa sposoby:
- Ocenić swoje węzły szybciej
- wyszukiwania mniej węzłów wymyślić samą odpowiedź
Twoim pierwszym problemem w optymalizacji kodu będzie pomiar. Skąd wiesz, że naprawdę zrobiłeś różnicę? Aby pomóc Ci w rozwiązaniu tego problemu, musisz upewnić się, że możesz zarejestrować niektóre statystyki podczas wyszukiwania ruchu. Te, które przechwytuję w moim silniku szachowym, to:
- Czas zakończenia wyszukiwania do został zakończony.
- Liczba węzłów poszukiwanej
To pozwoli ci odniesienia i przetestować zmiany. Najlepszym sposobem podejścia do testowania jest utworzenie kilku zapisanych gier z pozycji początkowej, środkowej i końcowej. Zapisz czas i liczbę szukanych węzłów w czerni i bieli. Po wprowadzeniu jakichkolwiek zmian zazwyczaj wykonuję testy przeciwko wyżej wymienionym zapisanym grami, aby sprawdzić, czy dokonałem ulepszeń w dwóch powyższych matrycach: liczba przeszukiwanych węzłów lub szybkość.
Aby jeszcze bardziej komplikować sytuację, po zmianie kodu można uruchomić silnik 3 razy i za każdym razem uzyskać 3 różne wyniki. Powiedzmy, że twój silnik szachowy znalazł najlepszy ruch w 9, 10 i 11 sekundach. To jest spread o około 20%. Czy ulepszyłeś silnik o 10% -20% lub po prostu zmieniłeś obciążenie swojego komputera? Skąd wiesz? Aby walczyć z tym, dodałem metody, które pozwolą mojemu silnikowi na grę przeciwko sobie, spowoduje to ruchy zarówno na biało, jak i na czarno. W ten sposób możesz przetestować nie tylko wariancję czasu nad jednym ruchem, ale także serię aż 50 ruchów w trakcie gry. Jeśli ostatnio gra trwała 10 minut, a teraz zajmuje 9, prawdopodobnie poprawiłeś swój silnik o 10%. Ponowne uruchomienie testu powinno to potwierdzić.
Znalezienie Wydajność Zyskuje
Teraz, gdy wiemy, jak mierzyć wzrost wydajności pozwala omówić jak zidentyfikować potencjalne zyski wydajności.
Jeśli jesteś w środowisku .NET, profiler .NET będzie twoim przyjacielem. Jeśli masz wersję Visual Studio dla programistów, jest ona dostępna za darmo, ale są też inne narzędzia innych firm, z których możesz korzystać. To narzędzie pozwoliło mi zaoszczędzić wiele godzin pracy, ponieważ dzięki temu dowiesz się, gdzie silnik spędza większość czasu i pozwala skoncentrować się na problematycznych miejscach. Jeśli nie masz narzędzia do profilowania, być może będziesz musiał w jakiś sposób zarejestrować znaczniki czasu, ponieważ twój silnik przechodzi przez różne etapy. Nie sugeruję tego. W tym przypadku dobry profiler jest wart swojej wagi w złocie. Red Gate ANTS Profiler jest drogi, ale najlepszy, jaki kiedykolwiek wypróbowałem. Jeśli nie możesz sobie na to pozwolić, skorzystaj przynajmniej z 14-dniowej wersji próbnej.
Twój profiler będzie niemiły zidentyfikować rzeczy dla ciebie, ale oto kilka małych lekcje nauczyłem pracy z C#:
- Zmienia wszystko prywatny
- Cokolwiek nie można zrobić prywatny, należy to uszczelnione
- Możliwe jest wykonanie wielu metod statycznych, takich jak .
- Nie twórz metod rozmownych, jedna metoda jest dłuższa niż 4 mniejsze .
- Tablica szachowa przechowywana jako tablica [8] [8] jest wolniejsza niż tablica [64]
- Zastępuje int, jeśli to możliwe, bajtem.
- Możliwe tylko po powrocie z Twoich metod już od .
- Stosy są lepsze niż listy
- Tablice są lepsze niż stosy i listy .
- Jeśli możesz określić rozmiar listy , zanim ją zapełnisz.
- Rzucanie, boksowanie, un-boxing jest złe.
dalszego wzrostu wydajności:
znajdę generacji przenieść i kolejność jest bardzo ważna. Jednak tutaj jest problem, jak widzę. Jeśli ocenisz wynik każdego ruchu przed posortowaniem i uruchomieniem Alpha Beta, będziesz w stanie zoptymalizować porządek ruchów, dzięki czemu uzyskasz bardzo szybkie wyłączenia Alfa Beta. Jest tak dlatego, że najpierw będziesz w stanie wypróbować najlepszy ruch. Jednak czas poświęcony na ocenę każdego ruchu zostanie zmarnowany. Na przykład, możesz ocenić wynik na 20 ruchach, posortować swoje ruchy wypróbować pierwsze 2 i odebrać odcięcie w ruchu nr 2. Teoretycznie straciłeś czas na pozostałe 18 ruchów.
Z drugiej strony, jeśli zrobisz lżejszą i znacznie szybszą ocenę, powiedz po prostu przechwytuj, twój sort nie będzie aż tak dobry i będziesz musiał przeszukać więcej węzłów (do 60% więcej). Z drugiej strony nie zrobiłbyś ciężkiej oceny każdego możliwego ruchu. Ogólnie rzecz biorąc to podejście jest zwykle szybsze zwykle szybsze.
Znalezienie idealnej równowagi pomiędzy posiadaniem wystarczającej ilości informacji do dobrego sortowania a brakiem dodatkowej pracy na ruchach, których nie wykorzystasz, pozwoli ci znaleźć ogromne zyski w swoim algorytmie wyszukiwania. Co więcej, jeśli wybierzesz uboższe podejście do sortowania, najpierw powinieneś zacząć od płytszego wyszukiwania, powiedz, że musisz przejść 3, posortuj swój ruch, zanim przejdziesz do głębszego wyszukiwania (często nazywa się to Iteracyjnym Pogłębieniem). To znacznie poprawi twój sort i pozwoli na przeszukiwanie znacznie mniej ruchów.
Możesz edytować swój post (np. Pytanie lub odpowiedź), aby umieścić dodatkowe informacje, takie jak ten. Wystarczy kliknąć link "edytuj" znajdujący się pod postem. – balpha
Po prostu z ciekawości, czy masz jakieś pojęcie, jak dobry (pod względem oceny Elo) jest twój program? Jestem wielkim entuzjastą szachów i myślałem o pisaniu programu szachowego od lat. Wiem, że najnowocześniejsze programy to niewiele więcej niż interfejsy dla ogromnych baz danych i bardzo chciałbym się przekonać, jak dobry ktoś może zrobić z algorytmem uczenia się. –
Będę komentować komentarz do Billa. Byłoby naprawdę interesujące zobaczyć twój program szachowy po jego uruchomieniu (lub nawet teraz, brzmi, jakbyś zrobił dużo pracy nad nim) – samoz