Étude comparative des performances

Condition optimale pour exécuter le workflow

Plusieurs investigations ont été menées afin de déterminer si n2p2 effectue une simple parallélisation via MPI ou s’il prend également en charge OpenMP (configuration multi-threads). Il semble que la configuration optimale pour n2p2 soit NODES=2 et THREADS=1. Cela signifie que n2p2 ne semble pas tirer efficacement parti d’une parallélisation multi-threads, mais uniquement d’une parallélisation multi-nœuds.

De plus, même lorsque le nombre de threads est fixé à 1, le nombre total d’époques d’apprentissage (c’est-à-dire la quantité de données entraînées) en fonction du nombre de nœuds n’augmente pas linéairement. L’approximation linéaire reste valable jusqu’à deux nœuds.

Une autre investigation de performance concerne la variation de la taille du jeu de données d’entrée. Le jeu de données complet consiste en une collection de 51 702 structures d’atomes de bore. Des sous-ensembles du jeu de données ont été étudiés par incréments de 5 000 structures en utilisant NODES=1, CORES=32, THREADS=1 et la commande mpirun -n 32. Dans ce jeu de données spécifique, 5 000 structures correspondent à 69,4 MB, tandis que 51 702 structures correspondent à 984,1 MB.

Le throughput en fonction du nombre de structures est représenté dans la Figure 1 et est défini comme le rapport entre le temps total d’entraînement et le nombre de structures :

$$ throughput=\frac{total_time(s)}{number_structures} $$

n2p2

Figure 1: Efficacité R en fonction du nombre de structures traitées. Axe des x en échelle log2

Le fait que n2p2 ne soit pas implémenté avec du multi-threading suggère de mener une investigation plus détaillée en fixant nos calculs de test avec NODES=1, CORES=32 et THREADS=1. Afin d’évaluer la tendance de l’efficacité en fonction du nombre de processus, le nombre d’époques a été fixé à 100 et le calcul d’entraînement a été exécuté avec la commande suivante :

mpirun -n num_proccess --bind-to core

num_process est le nombre de processus demandés, et num_process ∈ [1, 2, 4, 8, 16, 32, 64]. Dans le cas spécifique de num_process = 64, le nombre de nœuds est fixé à 2. L’option --bind-to core est importante pour garantir une parallélisation correcte des processus sans surcharger un seul socket. Plus d’informations sont disponibles dans la documentation officielle mpirun documentation officielle mpirun.

La Figure 2 montre l’efficacité (R) en fonction du nombre de processus. On peut observer que l’efficacité maximale est obtenue pour mpirun -n 1, puis diminue à mesure que le nombre de processus augmente. De plus, une comparaison entre l’installation native et l’installation Apptainer au sein d’un environnement Guix est présentée, montrant que la perte de performance liée à la version Apptainer est minime.

n2p2

Figure 2: Efficacité R en fonction du nombre de processus demandés. Axe des x en échelle log2.

À partir de cette étude, nous pouvons conclure que, pour les calculs n2p2, la configuration optimale est NODES=1, CORES=8, THREADS=1, avec 32 processus MPI. En effet, comme le montre la Figure 2, la tendance de mise à l’échelle linéaire est perdue au-delà de 8 processus ; par conséquent, le temps d’exécution total augmente de manière exponentielle. Une analyse complémentaire avec 64 processus sera réalisée pour compléter cette étude.

Concernant la comparaison entre l’installation native et la version Apptainer, nous observons que l’exécution avec Apptainer est plus lente. En particulier, elle nécessite environ 20 à 25 % de temps d’exécution total en plus. Néanmoins, elle permet de reproduire les calculs beaucoup plus facilement, ce qui représente un compromis raisonnable. Dans le cas spécifique de NODES=1, CORES=8, THREADS=1, 100 époques nécessitent 7 heures et 22 minutes avec Apptainer, contre 6 heures et 8 minutes avec l’installation native.