Outils pour utilisateurs

Outils du site


progc

Ceci est une ancienne révision du document !


Programmation en C / C++

Eléments de programmation multithread

Depuis le C++11, manipuler des threads en C++ est devenu plus simple et totalement portable. Voici un diaporama qui présente brièvement des fonctionnalités qui permettent de lancer des tâches sur des threads et les synchroniser: multithread_cpp.pdf. Deux couches d'abstraction sont disponibles: la première est simplement une surcouche objet des threads POSIX, le développeur manipule donc explicitement des threads; alors que la seconde est plus abstraite (et donc moins flexible) pour masquer les mécanismes multithread et simplifier le code. Les exemples de la présentation sont également disponibles: multithread_cpp.tgz.

Mesure des temps de calcul

Pour mesurer les temps de calcul d'un programme, une bonne solution consiste à utiliser la commande Unix time qui permet, si l'on regarde les temps user et system d'avoir une mesure précise et reproductible. Cependant, si on souhaite faire la mesure d'une partie de notre programme, il faut forcément toucher à notre code. On peut utiliser la fonction clock du C ou bien la classe chrono du nouveau C++, mais ces deux solutions mesurent le temps perçu (l'équivalent du temps real de la commande time), c'est-à-dire le temps où l'on attend pour avoir le résultat. Dans un environnement multitâche et multi-utilisateur, on ne peut pas se fier au temps perçu pour avoir une mesure précise et surtout reproductible.

La solution: getrusage

Une bonne solution pour mesurer un temps de calcul par programmation consiste donc à utiliser la fonction getrusage, disponible en standard pour C et C++ sous Linux. L'utilisation de cette fonction nécessite quelques précautions, donc voici un entête qui permet de faire abstraction des détails: [cpu_measure.hpp]. Prenons un exemple où l'on souhaite mesurer le temps d'exécution d'une fonction:

#include "cpu_measure.hpp"
 
long fibonacci(unsigned n) {
 if (n<2) return n;
 return (fibonacci(n-1) + fibonacci(n-2));
}
 
int main(void) {
 auto start = now();
 std::cout << "fibonacci(48) = " << fibonacci(48) << std::endl;
 auto end = now();
 
 auto duration = end-start;
 
 std::cout << "real " << duration.real << " ms" << std::endl;
 std::cout << "user " << duration.user << " ms" << std::endl;
 std::cout << "sys " << duration.system << " ms" << std::endl;
}

La fonction now s'occupe d'appeler getrusage (qui fournit des mesures de temps depuis le début de l'exécution du programme) et de synthétiser les résultats sous la forme temps real, user et system comme le fait la commande time. On effectue donc une mesure juste avant l'appel à la fonction à mesurer, une autre juste après, et on fait la différence des temps. Le résultat de ce programme:

real 17550 ms
user 17550 ms
sys 0 ms

Si on lance la commande time sur notre programme, on obtient des résultats équivalents:

real    0m17.615s
user    0m17.565s
sys     0m0.015s
progc.1526391207.txt.gz · Dernière modification : 2018/10/11 20:49 (modification externe)