rewording+add some graphs

This commit is contained in:
Mylloon 2024-04-26 13:05:00 +02:00
parent f271870c93
commit 961e6108f9
Signed by: Anri
GPG key ID: A82D63DFF8D1317F
3 changed files with 65 additions and 33 deletions

View file

@ -37,8 +37,10 @@
\def\coeur{c\oe{}ur} \def\coeur{c\oe{}ur}
\def\mone{\textit{Machine 1}} % fixe \def\mone{\textit{Machine 1}} % fixe
\def\mtwo{\textit{Machine 2}} % portable \def\mtwo{\textit{Machine 2}} % portable
\def\bone{\textit{Benchmark quicksort}} \def\qs{\enquote{quicksort}}
\def\btwo{\textit{Benchmark mandelbrot}} \def\mandel{\enquote{mandelbrot}}
\def\bone{\textit{Benchmark \qs}}
\def\btwo{\textit{Benchmark \mandel}}
\def\ws{\enquote{work-stealing}} \def\ws{\enquote{work-stealing}}
@ -149,17 +151,13 @@
\section{Descriptions} \section{Descriptions}
Description des différents algorithmes implémentés. Description des différents algorithmes implémentés.
\subsection{Séquentiel} \subsection{Séquentiel}\label{desc:seq}
Cette implémentation naïve correspond au mode \texttt{serial} Cette implémentation lance les tâches sur un \coeur.
de \texttt{quicksort.c}. Elle lance les tâches sans threads.
\subsection[Threads sans gestion]{Threads sans gestion} \subsection{Threads sans gestion}\label{desc:threads}
Cette implémentation correspond à simplement démarrer un nouveau thread Cette implémentation correspond à simplement démarrer un nouveau thread
pour chaque nouvelle tâche. pour chaque nouvelle tâche.
Comme cette implémentation n'ordonnance rien et que le nombre de threads créés
est important.
\subsection{Threads avec pile}\label{desc:th_pile} \subsection{Threads avec pile}\label{desc:th_pile}
Pour cette implémentation, nous gardons en mémoire une pile et nous démarrons Pour cette implémentation, nous gardons en mémoire une pile et nous démarrons
un nombre fixe de threads, et à chaque ajout d'une tâche, le thread l'empile. un nombre fixe de threads, et à chaque ajout d'une tâche, le thread l'empile.
@ -177,6 +175,12 @@ plus de tâches, il essaie d'en voler une à un autre thread.
\section{Comportement} \section{Comportement}
Analyse du comportement des différentes implémentations.
\subsection{Threads sans gestion}
Cette implémentation n'ordonnance rien, alors le nombre de threads
créés est important.
\subsection{Listes} \subsection{Listes}
Dans l'ordonnanceur LIFO, la liste est une pile. Chaque thread récupère le Dans l'ordonnanceur LIFO, la liste est une pile. Chaque thread récupère le
premier élément de la pile, c'est-à-dire le dernier à avoir été ajouté. premier élément de la pile, c'est-à-dire le dernier à avoir été ajouté.
@ -189,19 +193,19 @@ un vol, c'est le dernier élément qui est récupéré par le thread.
Dans mes implémentations, j'ai exclusivement utilisé des mutex ainsi que des Dans mes implémentations, j'ai exclusivement utilisé des mutex ainsi que des
variables de conditions pour endormir/réveiller mes threads. variables de conditions pour endormir/réveiller mes threads.
Pendant le développement, j'ai parfois utilisé \texttt{usleep} au lieu des Pendant le développement, j'ai parfois utilisé \texttt{usleep} pour interrompre
variables de conditions pour faire attendre les threads, mais j'ai obtenu de à temps donné un thread au lieu des variables de conditions pour faire
meilleurs résultats avec les variables de conditions. Aussi, je pense qu'avoir attendre les threads, mais j'ai obtenu de meilleurs résultats avec les variables
les variables de conditions m'assure que mon ordonnanceur fonctionne sur de conditions. Aussi, je pense qu'avoir les variables de conditions m'assure
n'importe quel CPU, qu'il soit lent ou rapide, avec des performances honnêtes. que mon ordonnanceur fonctionne sur n'importe quel CPU, qu'il soit lent ou rapide,
En effet, choisir une valeur qui fonctionne bien sur mon ordinateur n'assure pas avec des performances honnêtes. En effet, choisir une valeur qui fonctionne bien
qu'elle soit la meilleure pour un autre. sur mon ordinateur n'assure pas qu'elle soit la meilleure pour un autre processeur.
\subsection{Nombre de threads} \subsection{Nombre de threads}
Pour avoir un programme performant, il faut équilibrer le nombre de threads par Pour avoir un programme performant, il faut équilibrer le nombre de threads par
rapport aux nombres de \coeur{}s disponibles. Il faut également équilibrer la rapport aux nombres de \coeur{}s disponibles. Il faut également équilibrer la
création de nouvelles tâches par thread par rapport au véritable travail création de nouvelles tâches par thread par rapport au véritable travail
effectué par ledit thread. Par exemple, dans le \btwo, chaque tâche soit crée effectué par ledit thread. Par exemple, dans le \btwo, chaque tâche crée soit
quatre nouvelles tâches, soit calcule une portion de l'image. Une plus grande quatre nouvelles tâches, soit calcule une portion de l'image. Une plus grande
création de tâches favorise le \ws~parce qu'une pile unique atteint ses limites création de tâches favorise le \ws~parce qu'une pile unique atteint ses limites
quand trop de tâches sont ajoutées, car les threads n'ont pas le temps quand trop de tâches sont ajoutées, car les threads n'ont pas le temps
@ -218,10 +222,19 @@ de \texttt{gcc}, sur 2 machines.
\item \textbf{8 \coeur{}s} pour la \mtwo. \item \textbf{8 \coeur{}s} pour la \mtwo.
\end{enumerate} \end{enumerate}
Le programme utilisé pour tester les implémentations est le quicksort fourni Les benchmarks utilisés pour tester les implémentations sont le \qs~fourni
et une adaptation de mandelbrot fournie dans le et une adaptation de \mandel~fournie dans le
\href{https://www.irif.fr/~jch/enseignement/systeme/tp10.pdf}{TP 10}. \href{https://www.irif.fr/~jch/enseignement/systeme/tp10.pdf}{TP 10}.
Pour lancer plusieurs fois le programme, j'ai utilisé la commande
\mintinline{fish}|for| du shell \texttt{fish}. Pour exemple, voici la commande
pour lancer l'ordonnanceur 100 fois avec \qs~et tous les threads disponibles :
\begin{figure}[H]
\centering
\mintinline{fish}|for i in (seq 100); ./ordonnanceur.elf -qt 0; end|
\end{figure}
\subsection{Séquentiel}\label{stats:seq} \subsection{Séquentiel}\label{stats:seq}
\begin{description} \begin{description}
\item[\bone] \hspace{1em} \item[\bone] \hspace{1em}
@ -243,7 +256,16 @@ et une adaptation de mandelbrot fournie dans le
\statPlot{serial}{en séquentiel} \statPlot{serial}{en séquentiel}
Ce programme ne bénéficie pas de toute la puissance de la machine. \begin{figure}[H]
\centering
\includegraphics[alt={Graphique},width=\textwidth]{imgs/bottom-seq.jpg}
\caption{Exploitation des ressources sur la \mone~avec \docref{desc:seq}}
\label{fig:btm-seq}
\end{figure}
Ce programme ne bénéficie pas de toute la puissance de la machine,
visible notamment grâce à la \autoref{fig:btm-seq} où l'on voit que seulement
un \coeur~est utilisé.
\subsection{Threads sans gestion}\label{stats:th_ges} \subsection{Threads sans gestion}\label{stats:th_ges}
@ -267,14 +289,25 @@ Ce programme ne bénéficie pas de toute la puissance de la machine.
\statPlot{solution1}{avec des threads} \statPlot{solution1}{avec des threads}
La création des threads pour chaque tâche crée un énorme \begin{figure}[H]
goulot d'étranglement qui réduit de grandement les performances. \centering
\includegraphics[alt={Graphique},width=\textwidth]{imgs/bottom-threads.jpg}
\caption{Exploitation des ressources sur la \mone~avec \docref{desc:threads}}
\label{fig:btm-threads}
\end{figure}
Le temps d'exécution étant long, nous pouvons voir les threads via la commande La création des threads pour chaque tâche crée un énorme goulot
\texttt{top} : \mintinline{bash}|top -Hp $(pgrep ordonnanceur)|. d'étranglement qui réduit grandement les performances. On le voit notamment
sur la \autoref{fig:btm-threads} où tous les \coeur{}s sont utilisés, mais très
peu. Créer de façon incontrôlée des threads n'est pas une manière efficace de
répartir la charge.
Pour augmenter les performances, il faut avoir une taille fixe de threads crée, % Le temps d'exécution étant long, nous pouvons voir les threads avec la commande
et donc il faut gérer les tâches et décider de quelle tâche va sur quel thread. % \texttt{top} : \mintinline{bash}|top -Hp $(pgrep ordonnanceur)|.
Pour augmenter les performances, il faut donc avoir une taille fixe de threads,
et par conséquent, il faut gérer les tâches et décider de quelle tâche va sur
quel thread.
\subsection{Threads avec pile}\label{stats:stack} \subsection{Threads avec pile}\label{stats:stack}
\begin{description} \begin{description}
@ -305,7 +338,7 @@ les performances sont aussi améliorées par rapport aux tests de
\docref{stats:seq}. \docref{stats:seq}.
Dans la \autoref{fig:btm-lifo}, nous observons que les \coeur{}s du CPU ne sont pas Dans la \autoref{fig:btm-lifo}, nous observons que les \coeur{}s du CPU ne sont pas
tous utilisés à 100 \%. Ceci est dû au fait que l'accès à la liste des tâches est tous utilisés à 100~\%. Ceci est dû au fait que l'accès à la liste des tâches est
limité, car partagé entre les threads. limité, car partagé entre les threads.
\begin{figure}[H] \begin{figure}[H]
@ -367,8 +400,8 @@ Dans cette implémentation, nous n'utilisons plus une pile, mais un deque de tâ
Cette façon de faire est légèrement meilleur que \docref{desc:th_pile}. Cette façon de faire est légèrement meilleur que \docref{desc:th_pile}.
Dans la \autoref{fig:btm-ws}, nous observons que les \coeur{}s du CPU sont Dans la \autoref{fig:btm-ws}, nous observons que les \coeur{}s du CPU sont
proches de 100 \% d'utilisation. Comparé à \docref{stats:stack}, nous gagnons proches de 100~\% d'utilisation. Comparé à \docref{stats:stack}, nous gagnons
en moyenne \approx~10 \% de l'utilisation du processeur dans son entièreté. en moyenne \approx~10~\% de l'utilisation du processeur dans son entièreté.
\begin{figure}[H] \begin{figure}[H]
\centering \centering
@ -459,13 +492,12 @@ le \btwo~fonctionnait correctement. Ce qui donne la \autoref{fig:mandelbrot}.
\begin{figure}[H] \begin{figure}[H]
\centering \centering
\includegraphics[alt={Fractale mandelbrot},width=0.7\textwidth]{imgs/mandelbrot.jpg} \includegraphics[alt={Fractale \mandel},width=0.7\textwidth]{imgs/mandelbrot.jpg}
\caption{Example de Mandelbrot} \caption{Example de \mandel}
\label{fig:mandelbrot} \label{fig:mandelbrot}
\end{figure} \end{figure}
Les captures d'écran de la \autoref{fig:btm-lifo} et de la \autoref{fig:btm-ws} Les captures d'écran d'exploitation des ressources ont été prises via le
ont été prises via le
programme \href{https://github.com/ClementTsang/bottom}{bottom}. programme \href{https://github.com/ClementTsang/bottom}{bottom}.
\end{document} \end{document}

BIN
report/imgs/bottom-seq.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB