Table des matières
Mesure des temps de calcul
Reproductibilité des temps de calcul
Si vous souhaitez reproduire vos temps de calcul, ou comparer les temps de calcul de différents programmes vous devez utiliser le cluster SLURM (et non les machines en libre accès sur lesquelles les temps de calcul peuvent subir de grandes variations en fonction de leur taux d'utilisation).
Pour connaître les spécificités de la machine sur laquelle vous lancez votre job vous pouvez appeler ce scriptgetcpuinfo dans votre script de soumission (merci à Bruno Bachelet pour ce fichier).
Exemple de script de soumission qui utilise getcpuinfo :
#!/bin/bash # ================================================ # OPTIONS #SBATCH --ntasks=1 #SBATCH --cpus-per-task=1 #SBATCH --time=10:00 #SBATCH --mem-per-cpu=10 # ================================================= # exécution du script getcpuinfo puis du progamme ./getcpuinfo ./exe
Logiciel multithread
Lorsque vous utilisez un logiciel qui gère automatiquement sa quantité de threads, il est important de vérifier de quelle manière il estime le nombre de coeurs qui sont à sa disposition pour savoir combien de threads sont alloués par rapport au nombre de coeurs effectivement disponibles. Si le ratio est trop important, vous aurez certainement une perte significative de performance.
Certains logiciels (comme Cplex) tentent d'utiliser par défaut tous les cœurs de la machine. Il est important que l'utilisateur paramètre le nombre de cœurs qu'il souhaite effectivement utiliser au niveau du logiciel pour qu'il ne dépasse pas le nombre de cœurs alloués par SLURM. Par exemple si vous demandez à SLURM 8 coeurs alors vous devez paramétrer votre programme pour qu'il n'utilise pas plus de 8 threads. Dans le cas contraire, il est possible que plusieurs threads soient traités par un même cœur ce qui affecterait les temps de calcul.
Par programmation, il existe plusieurs manières d'estimer le nombre de coeurs disponibles pour le processus courant, ce qui permet de déterminer combien de threads il faut créer pour les besoins d'un programme. En voici trois en C / C++: std::hardware_concurrency
(à partir de C++11), omp_max_threads
(OpenMP), sched_getaffinity
(module standard Linux). Le code suivant teste les trois solutions: cores_estimator.cpp. Il semblerait que les approches avec OpenMP et Sched fournissent les bonnes informations, alors que celle du C++ indique le nombre de coeurs de la machine et non celui de votre réservation SLURM.
Pour plus de détails, voir la page Programmation en C / C++.
Temps de calcul et localisation des cœurs
Fichier /proc/cpuinfo
Les informations détaillées sur les processeurs d'une machine sont disponibles dans le fichier /proc/cpuinfo
. Dans ce fichier :
- processor donne le numéro du processeur (= cœur logique = CPU dans le vocabulaire de SLURM)
- core id donne le numéro de cœur physique dans le socket correspondant au processeur
- physical id donne le numéro de socket auquel appartient le processeur
Si deux processeurs ont le même physical id et le même core id alors il s'agit d'un même cœur physique hyperthreadé.
Commandes utiles
lscpu
permet d'afficher une synthèse des infos sur les processeurs de la machine
free
permet de connaître la quantité de mémoire disponible
mpstat -P ALL <sec>
permet d'afficher l'activité de chaque cœur (logique) toutes les sec secondes.
/usr/bin/time -v
suivi du nom du programme donne des informations sur le temps de calcul et les ressources mémoire utilisées (il est nécessaire de préciser le chemin complet de la commandetime
si on utilise l'option-v
)
lspci | grep VGA
affiche les cartes graphiques disponibles
taskset -cp $$
indique l'affinité CPU du processus courant ($$
), autrement dit les numéros des coeurs alloués à votre processus (SLURM ou autre).
Fonction getrusage (C/ C++ sous Linux)
Le fonction getrusage, disponible en C / C++ sur les OS linux, permet de récupérer des informations sur la consommation de ressources du programme depuis lequel est elle appelée.
Les exemples de fonctions ci-dessous permettent de récupérer le temps de calcul et la consommation de RAM.
#include <sys/resource.h> #include <sys/time.h> double give_time() { struct rusage ru; struct timeval tim; getrusage(RUSAGE_SELF, &ru); tim = ru.ru_utime; //temps systeme en secondes double stime = (double)tim.tv_sec + (double)tim.tv_usec / 1000000.0; return stime; } double give_maxMemoryUsed() { struct rusage ru; getrusage(RUSAGE_SELF, &ru); return ru.ru_maxrss; //(en kbytes ~ Max Resident size de la commande time -v) }