• Aucun résultat trouvé

Nous avons remarqué que certains alignements devaient être évités au niveau de l’allocateur notamment pour les gros tableaux. De plus, nous avons montré dans la section précédente qu’il était possible de détecter (malgré de possibles faux positifs) les fonctions à problème. On peut donc se demander s’il n’est pas possible d’exploiter les données fournies par l’outil précédent pour générer une politique d’allocation exploitant ces informations en considérant une première étape de profilage pour les générer. En théorie, il pourrait être possible de considérer qu’une allocation établie dans une fonction particulière aura par la suite un cycle de vie relativement déterministe. Ceci est notamment vrai pour les gros tableaux habituellement présents en nombre limité. La génération de règles d’alignements à éviter semble donc possible à partir des profils précédents. Ceci est d’autant plus vrai que les points à éviter sont rares en rapport de l’espace des alignements possibles.

D’un point de vue pratique, on se heurte toutefois à la difficulté de trouver un moyen simple et efficace d’associer un tableau à une information extraite d’un profile d’une exécution précé- dente. Il ne paraît pas raisonnable de remontrer la pile d’appels pour chaque allocation. Nous avons donc préféré tester diverses heuristiques de génération d’alignements ne nécessitant pas de profil. À titre de comparaison, sur un programme simple nous avons tout de même mis en place une méthode basée sur l’ordre d’allocation des tableaux. Cette méthode basique permet

3.8. Conclusion 0.0001 0.001 0.01 0.1 1 10 100 0 5 10 15 20 25 400x400 800x800 1000x1000 Ratio temporel de l a fonction (%)

Nombre de tableaux fonction du coût relatif des fonctions

Nombre de tableaux utilisés par la fonction

100x100

FIGURE3.15 – Distribution de l’utilisation mémoire des fonctions du programme EulerMHD sur la

base du temps d’exécution relatif des fonctions et du nombre de tableaux manipulés. Remarquons que la distribution est pour ce programme indépendante de la taille du problème.

ainsi d’évaluer les gains potentiels d’un apport d’information extérieur. L’alignement de l’adresse de base du tableau est choisi parmi un intervalle de [0, 4Ko[ selon les règles qui suivent :

Aléatoire : Les valeurs sont choisies aléatoirement avec un pas de 16 ou 64 octets.

Incrément : Les valeurs sont choisies selon une méthode tourniquet en incrémentant une va-

riable globale de 16 ou 64 octets.

Groupe : L’algorithme génère des groupes rassemblant les tableaux utilisés simultanément dans

les différentes fonctions comptant pour plus que 1% du temps d’exécution total. Les groupes ayant des tableaux communs sont fusionnés de sorte à agréger les tableaux en relation pour le programme dans son ensemble. Chaque groupe est alors associé à un décalage global et les alignements des tableaux sont répartis de sorte à être dispersés au sein de l’espace [0, 4Ko[ avec un pas minimum de 16 ou 64 octets.

Les résultats expérimentaux montrent toutefois (figure 3.16) que le choix d’une politique strictement aléatoire conduit au meilleur gain, obtenant des performances aussi bonnes qu’une méthode beaucoup plus lourde basée sur l’exploitation de profils. Remarquons qu’empirique- ment l’utilisation d’une discrétisation par pas de 64o de l’espace des alignements possible semble apporter les meilleurs résultats. Cette observation est cohérente avec l’utilisation de lignes de cache de 64 octets par le matériel.

3.8

Conclusion

Dans ce chapitre, nous avons étudié en détail les problèmes d’interférences pouvant surve- nir entre les politiques de gestion de la mémoire au niveau de l’OS et celles mises en place au niveau de l’allocateur. Nous avons rappelé le problème de fuite de cache observé sous Linux et traité par des méthodes de coloration de pages par d’autres OS. Ces approches sont souvent dé- crites dans les théories des mécanismes de pagination. Nous avons toutefois montré que le choix

glibc rand rand64 incr16 incr32 incr64 incr128 groups groups64 0 100 200 300 400

Comparaisoin de différentes méthodes d'alignement

Temps (s)

Méthode d'alignement (s)

FIGURE 3.16 – Distribution de différentes exécutions du programme EulerMHD pour différentes

règles d’alignement.

d’une méthode de coloration n’était pas sans conséquence et que les techniques habituellement employées impliquaient une prise en compte explicite du problème au niveau de l’allocateur mémoire en espace utilisateur (malloc).

Nous avons également observé que les allocateurs actuels tendent à prendre des décisions conduisant par défaut aux pertes de performances observées dans ce chapitre. Il en ressort que la méthode aléatoire exploitée par Linux évite ce type de problème montrant notamment en parallèle une plus grande résistance à ces cas pathologiques. Certaines améliorations ont donc été proposées tant au niveau des politiques de coloration qu’au niveau de l’allocateur, les deux pouvant être utilisées de manière complémentaire. Remarquons que l’étude [ADM11] décrit le problème de placement des macros blocs de manière générique, mais ne traite pas de leur inter- action avec la politique de pagination sous-jacente.

Dans la suite, nous allons discuter les problématiques entourant le développement d’un allo- cateur parallèle avec support NUMA. Nous nous intéresserons alors aux performances des fautes de pages pour l’allocation de grands tableaux nécessaires en HPC.

Chapitre 4

Mécanismes d’allocations parallèles et

contraintes mémoires

Dans le chapitre précédent, nous nous sommes attachés à étudier les interactions pouvant s’établir entre la politique de l’OS et l’allocateur mémoire en terme de choix des adresses. Ici, nous allons décrire la mise en place d’un allocateur parallèle dans le cadre du projet MPC. Nous décrirons donc dans un premier temps les contraintes prises en compte et l’état des lieux des allocateurs disponibles. Une fois de plus nous nous intéresserons principalement à la probléma- tique de gestion de grands volumes de données, notamment vis-à-vis des performances de leur allocation par l’OS.

Nous verrons notamment qu’avec un nombre croissant de cœurs, Linux est affecté par un problème d’extensibilité des performances de ses fautes de pages. Le problème sera traité ici du point de vue de l’allocateur en visant à réduire l’interaction de ce dernier avec l’OS. Nous discuterons notamment la possibilité d’établir un compromis entre consommation mémoire et efficacité d’allocation des grands segments. Pour ce faire, nous considérerons un environnement dans lequel nous serons amenés à faire plus attention aux problématiques de consommation.

Nous développerons également les points concernant le support des architectures NUMA. Ces architectures nécessitent une prise en charge explicite par l’allocateur lorsque l’on fonc- tionne en mode multithread. Nous verrons à cette occasion que MPC nous permet d’exploiter des informations utiles, non disponibles en temps normal.

4.1

Approche générale

Comme nous l’avons discuté en section2.4, un allocateur mémoire a pour principal objectif de maintenir à jour une liste de blocs non utilisés et d’offrir un algorithme efficace pour répondre aux requêtes de l’utilisateur. Il gère également les échanges de mémoire avec l’OS. Rappelons toutefois qu’il n’est pas possible de prédire les propriétés des requêtes à venir. Les algorithmes sé- lectionnés se construisent donc sur la base d’heuristiques. Un algorithme sera considéré comme bon, s’il est affecté par un nombre réduit de cas problématiques (explosion de la consommation mémoire ou du temps de décision) et qu’il offre de bonnes performances.

À ce titre, de nombreuses stratégies ont été évaluées au fil du temps. On pourra notamment se référer à une étude bilan réalisée par Wilson en 1995 [WJNB95] pour obtenir une vue des différentes techniques mises en place dans les allocateurs de l’époque. Cette étude traite notam- ment le problème de fragmentation mémoire. Willson y décrit le problème sous la forme de trois niveaux conceptuels. La stratégie tente d’exploiter les régularités du flux de requête. La politique est un choix de procédure implémentable pour placer les blocs en mémoire. La mécanique est un

ensemble d’algorithmes et structures de données permettant d’implémenter la politique. Cette séparation peut s’appliquer de manière générale à tout algorithme, mais prend une tournure toute particulière dans la conception d’un allocateur mémoire. Ce dernier doit en effet résoudre simultanément le problème d’allocation des éléments demandés et de ses propres métadonnées. Cette double problématique contraint largement les algorithmes en les couplant fortement à la structure des métadonnées.

Nous commencerons donc par décrire les besoins particuliers auxquels on s’intéresse afin de pouvoir construire une stratégie adaptée. Nous étudierons également les différents allocateurs disponibles allant dans le sens de nos besoins. Nous entrerons finalement dans la description de nos politiques et mécaniques d’allocation propres.