|
1 | 1 | \chapter{Analysis and evaluation}\label{cap:analysis} |
2 | 2 |
|
3 | | -This chapter documents the implementation of the following techniques used to improve the chess engine: |
| 3 | +This chapter presents an analysis of the performance of the chess engine through profiling, identifying its most computationally intensive components. We then evaluate the effectiveness of the improvement techniques described in ~\cref{cap:ImprovementTechniques}. Finally, we compare the performance of \textit{AlphaDeepChess} against \textit{Stockfish}, and examine its position within the Elo rating distribution on \textit{Lichess.org}. |
4 | 4 |
|
5 | | -\begin{itemize}[itemsep=1pt] |
6 | | - \item Transposition tables with zobrist hashing. |
7 | | - \item Move generator with magic bitboards and PEXT instructions. |
8 | | - \item Evaluation with king safety and piece mobility parameters. |
9 | | - \item Multithread search. |
10 | | - \item Search with Late move Reductions. |
11 | | -\end{itemize} |
| 5 | +\newpage |
12 | 6 |
|
| 7 | +\section{Profiling} |
| 8 | +In order to analyze the performance of our chess engine and identify potential bottlenecks where the code consume the most execution time, we used the \texttt{perf} tool available on Linux systems. \texttt{perf} provides robust profiling capabilities by recording CPU events, sampling function execution, and collecting stack traces ~\cite{PerfLinux}. |
13 | 9 |
|
14 | | -\newpage |
| 10 | +\vspace{1em} |
15 | 11 |
|
16 | | -\noindent Achieving this level of efficiency and quality requires a well-structured development process. For this reason, we adopted a systematic methodology to guide the implementation and continuous improvement of our engine. |
| 12 | +\noindent We run the engine under \texttt{perf} using the following commands: |
17 | 13 |
|
18 | | -\section{Methodology} |
| 14 | +\begin{lstlisting}[language=bash, caption={Profiling \textit{AlphaDeepChess} with perf}, frame=single, breaklines=true] |
| 15 | +# Record performance data with function stack traces |
| 16 | +sudo perf record -g ./build/release/AlphaDeepChess |
19 | 17 |
|
20 | | -Once the basic foundations are established with an initial version of the essential components or modules (which will be described later), our workflow follows an iterative process: first, we search for existing information on each topic, analyze it, implement a solution, and then profile the implementation to identify bottlenecks. After locating performance issues, we optimize the relevant parts, and finally, compare the new version with the previous one to assess improvements. |
| 18 | +# Display interactive report |
| 19 | +sudo perf report -g --no-children |
| 20 | +\end{lstlisting} |
21 | 21 |
|
22 | | -\vspace{1em} |
| 22 | +\noindent After recording, \texttt{perf report} opens an interactive terminal interface where functions are sorted by CPU overhead, allowing us to easily identify performance-critical regions. |
| 23 | + |
| 24 | +\vspace{2em} |
23 | 25 |
|
24 | | -\noindent Then, at a given moment, we can decide to take action and try to determine the strength of the engine with the last functional version. |
| 26 | +\noindent First, we profile the basic architecture of the engine implemented in~\cref{cap:descripcionTrabajo}, and then evaluate it again after applying the optimizations described in~\cref{cap:ImprovementTechniques}. |
25 | 27 |
|
26 | | -\subsection*{Profiler} |
| 28 | +\subsection*{Profiling of basic engine architecture} |
27 | 29 |
|
28 | | -First, in order to analyze the performance of our chess engine and identify potential bottlenecks, we used the \texttt{perf} tool available on Linux systems. \texttt{perf} provides robust profiling capabilities by recording CPU events, sampling function execution, and collecting stack traces. |
| 30 | +\noindent As shown in~\cref{tab:profilingBasic}, the profiling results indicate that the majority of the total execution time is spent in the legal move generation function. Specifically, the functions \texttt{generate\_legal\_moves}, \texttt{calculate\_moves\_in\_dir}, and \texttt{update\_danger\_in\_dir} together account for over 72\% of the total overhead. Therefore, the optimizations on this component are expected to yield significant performance improvements. |
| 31 | + |
| 32 | +\begin{table}[H] |
| 33 | + \centering |
| 34 | + \begin{tabular}{|l|r|} |
| 35 | + \hline |
| 36 | + \textit{Symbol} & \textit{Overhead} \\ |
| 37 | + \hline |
| 38 | + \texttt{generate\_legal\_moves} & 36.07\% \\ |
| 39 | + \texttt{calculate\_moves\_in\_dir} & 19.30\% \\ |
| 40 | + \texttt{evaluate\_position} & 16.63\% \\ |
| 41 | + \texttt{update\_danger\_in\_dir} & 16.23\% \\ |
| 42 | + \texttt{calculate\_king\_moves} & 1.24\% \\ |
| 43 | + \texttt{quiescence\_search} & 0.96\% \\ |
| 44 | + \texttt{...} & ... \\ |
| 45 | + \hline |
| 46 | + \end{tabular} |
| 47 | + \caption{Profiling results of the basic engine implementation.} |
| 48 | + \label{tab:profilingBasic} |
| 49 | +\end{table} |
29 | 50 |
|
30 | 51 | \vspace{1em} |
31 | 52 |
|
32 | | -\noindent Our profiling goal is to identify which parts of the code consume the most execution time. We run the engine under \texttt{perf} using the following commands: |
| 53 | +\subsection*{Profiling with improvement techniques} |
33 | 54 |
|
34 | | -\begin{lstlisting}[language=bash, caption={Profiling \textit{AlphaDeepChess} with perf}, frame=single, breaklines=true] |
35 | | -# Record performance data with function stack traces |
36 | | -sudo perf record -g ./build/release/AlphaDeepChess |
| 55 | +\noindent As shown in~\cref{tab:profilingImprovements}, the updated profiling results demonstrate a successful reduction in the computational cost of move generation. The execution time is now more evenly distributed across various modules, with position evaluation emerging as the new primary performance bottleneck. This shift confirms the effectiveness of the implemented optimization techniques. |
37 | 56 |
|
38 | | -# Display interactive report |
39 | | -sudo perf report -g --no-children |
40 | | -\end{lstlisting} |
| 57 | +\begin{table}[H] |
| 58 | + \centering |
| 59 | + \begin{tabular}{|l|r|} |
| 60 | + \hline |
| 61 | + \textit{Symbol} & \textit{Overhead} \\ |
| 62 | + \hline |
| 63 | + \texttt{evaluate\_position} & 31.90\% \\ |
| 64 | + \texttt{update\_attacks\_bb} & 22.62\% \\ |
| 65 | + \texttt{generate\_legal\_moves} & 22.71\% \\ |
| 66 | + \texttt{order\_moves} & 3.95\% \\ |
| 67 | + \texttt{make\_move} & 3.83\% \\ |
| 68 | + \texttt{alpha\_beta\_search} & 1.66\% \\ |
| 69 | + \texttt{...} & ... \\ |
| 70 | + \hline |
| 71 | + \end{tabular} |
| 72 | + \caption{Profiling results after applying optimization techniques.} |
| 73 | + \label{tab:profilingImprovements} |
| 74 | +\end{table} |
| 75 | + |
| 76 | +\newpage |
41 | 77 |
|
42 | | -\noindent After recording, \texttt{perf report} opens an interactive terminal interface where functions are sorted by CPU overhead. This allows us to prioritize which functions to optimize. |
| 78 | +\section{cutechess} |
43 | 79 |
|
44 | 80 | \noindent The most common way to measure the strength of a chess engine is by playing games against other engines and analyzing the results. To quantify this strength, the Elo rating system is used. Elo is a statistical rating system originally developed for chess, which assigns a numerical value to each player (or engine) based on their game results against opponents of known strength. When an engine wins games against higher-rated opponents, its Elo increases; if it loses, its Elo decreases. This allows for an objective comparison of playing strength between different engines. |
45 | 81 |
|
|
0 commit comments