Estimer efficacement la vitesse à laquelle une boucle s'exécute

Le problème exposé dans ce sujet a été résolu.

Bonjour,

Je suis actuellement en train de bosser sur un programme de rendu de fractal. Je prévois quelques fonctionnalités assez complexes et l'une d'entre elle est d'avoir un indicateur en temps réel de la vitesse à laquelle la boucle principale s'exécute et l'afficher toutes les secondes ou tous les dixièmes de seconde.

La solution la plus simple est d'appeler une fonction type time()1 à chaque itération et de faire les calculs nécessaires à partir de là. Le problème avec cette approche est que l'appel à time() va générer un appel système qui risque d'avoir un coût non négligeable comparé à celui de l'exécution du code à l'intérieur de la boucle. Les performances étant un des points les plus critiques de mon programme.

Une autre solution serait de faire l'appel à time() toute les x itérations, sauf que ce x n'est pas connu à l'avance et risque fort de varier durant l'exécution du programme.

Une autre solution à laquelle j'ai pensé est d'avoir un compteur incrémenté à chaque itération et d'avoir un thread séparé pour calculer la vitesse d'exécution toutes les x millisecondes. Sauf que l'itérateur doit alors être thread-safe, ce qui risque là aussi d'impacter les performances, que ce soit à cause de l'utilisation de verrou ou simplement à cause de la synchronisation des caches du processeur.

La dernière solution qui me semble faisable est d'avoir un système similaire à ma deuxième solution, mais avec une estimation dynamique du nombre d'itérations à effectuer avant d'appeler time() pour avoir un impact négligeable sur les performances tout en ayant une estimation correcte de la vitesse d'exécution du code.

Sachant que le problème me semble quelque chose de potentiellement "courant", je suppose qu'il doit déjà y avoir une librairie qui fait ça beaucoup mieux que ce que je pourrais faire, mais je n'ai rien trouvé (en tout cas, rien avec une recherche Google et rien dans Boost), donc je me demande si mon approche est correcte.

Est-ce ça vous semble sensé?


  1. oui, je sais qu'il y a des objets dédiés en C++, c'était juste pour l'exemple. 

J'ai trouvé ça sur cplusplus

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// high_resolution_clock example
#include <iostream>
#include <ctime>
#include <ratio>
#include <chrono>

int main ()
{
  using namespace std::chrono;

  high_resolution_clock::time_point t1 = high_resolution_clock::now();

  std::cout << "printing out 1000 stars...\n";
  for (int i=0; i<1000; ++i) std::cout << "*";
  std::cout << std::endl;

  high_resolution_clock::time_point t2 = high_resolution_clock::now();

  duration<double> time_span = duration_cast<duration<double>>(t2 - t1);

  std::cout << "It took me " << time_span.count() << " seconds.";
  std::cout << std::endl;

  return 0;
}
+0 -2

Un point qu'il faut bien comprendre : L'informatique c'est quantique : mesurer va changer la valeur, il faut juste perturber le moins possible.

Toutes tes options me paraissent possibles. - Le première en wrappant ta fonction avec ce que montre d3m0t3p - Je vois pas en quoi la seconde te pose un soucis. Faire une moyenne sur 50 ou 100 appels se fait bien. - Pour la 3eme Avec un simple atomic<int>donné à une tâche asynchrone, le surcout de com entre thread devrait être minimal.

Sinon, benchmark par google (même si c'est plus orienté unittest), et une vidéo légèrement off-topic sur le sujet

+3 -0

Le problème de la deuxième solution, c'est que je peux très bien avoir un moment où la boucle tourne à 10 itérations secondes et un autre où c'est 1 million (ça restera cependant assez cohérent sur une courte période de temps). Donc en fixant le nombre d'itération pour chaque calcul, je risque fort de me retrouver à avoir un moment où les données sont mise à jour pas assez souvent et un autre où j'impacte les performances.

Par contre, l'idée d'utiliser atomic correspond bien à ce qu'il me faut. Non seulement, gérer l'affichage et le temps dans un thread séparé me permet d'avoir un fonctionnement simple, mais c'est peut-être la solution qui impacte le moins les performances.

Merci à vous :)

La grosse majorité des profileurs ralentissent énormément le code et permettent après l'exécution d'avoir des informations sur l'exécution du code.

Mon but est très différent puisque je souhaite avoir au sein de programme un moyen de connaître la vitesse d'exécution actuelle et ce en impactant les performances au minimum.

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte