403 votes

Mesurer facilement le temps écoulé

J'essaie d'utiliser temps() pour mesurer les différents points de mon programme.

Ce que je ne comprends pas, c'est pourquoi les valeurs avant et après sont les mêmes ? Je comprends que ce n'est pas la meilleure façon de profiler mon programme, je veux juste voir combien de temps quelque chose prend.

printf("**MyProgram::before time= %ld\n", time(NULL));

doSomthing();
doSomthingLong();

printf("**MyProgram::after time= %ld\n", time(NULL));

J'ai essayé :

struct timeval diff, startTV, endTV;

gettimeofday(&startTV, NULL); 

doSomething();
doSomethingLong();

gettimeofday(&endTV, NULL); 

timersub(&endTV, &startTV, &diff);

printf("**time taken = %ld %ld\n", diff.tv_sec, diff.tv_usec);

Comment lire un résultat de **time taken = 0 26339 ? Cela signifie-t-il que 26 339 nanosecondes = 26,3 msec ?

Qu'en est-il **time taken = 4 45025 Cela signifie-t-il 4 secondes et 25 msec ?

10 votes

Je ne comprends pas la question. Bien sûr, les valeurs sont différentes. Le temps a passé entre les deux, donc time() renvoie une valeur différente.

1 votes

Que voulez-vous dire par "Je ne comprends pas pourquoi les valeurs avant et après sont différentes" ? Vous obtenez l'heure actuelle (en secondes depuis le 1er janvier 1970) à l'aide de la fonction time(NULL) ... la deuxième fois que vous l'appellerez sera N secondes après la première et donc ... différente (à moins que ce que vous êtes en train de faire ne prenne pas une seconde pour se terminer ... dans ce cas, ce sera la même chose que la première).

1 votes

Pouvez-vous nous dire ce que cela imprime, et combien de temps cela prend si vous le chronométrez avec un chronomètre ou une horloge murale (ou un calendrier) ?

558voto

user3762106 Points 4479
//***C++11 Style:***
#include <chrono>

std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();

std::cout << "Time difference = " << std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count() << "[µs]" << std::endl;
std::cout << "Time difference = " << std::chrono::duration_cast<std::chrono::nanoseconds> (end - begin).count() << "[ns]" << std::endl;

340voto

Nikos Athanasiou Points 7015

0 - Delta

Utilisez une fonction delta pour calculer les différences de temps :

auto start = std::chrono::steady_clock::now();
std::cout << "Elapsed(ms)=" << since(start).count() << std::endl;

since accepte n'importe quel point de temps et produit n'importe quelle durée (les millisecondes sont la valeur par défaut). Il est défini comme suit :

template <
    class result_t   = std::chrono::milliseconds,
    class clock_t    = std::chrono::steady_clock,
    class duration_t = std::chrono::milliseconds
>
auto since(std::chrono::time_point<clock_t, duration_t> const& start)
{
    return std::chrono::duration_cast<result_t>(clock_t::now() - start);
}

Demo

1 - Minuterie

Utiliser une minuterie basée sur std::chrono :

Timer clock; // Timer<milliseconds, steady_clock>

clock.tick();
/* code you want to measure */
clock.tock();

cout << "Run time = " << clock.duration().count() << " ms\n";

Demo

Timer est défini comme suit :

template <class DT = std::chrono::milliseconds,
          class ClockT = std::chrono::steady_clock>
class Timer
{
    using timep_t = typename ClockT::time_point;
    timep_t _start = ClockT::now(), _end = {};

public:
    void tick() { 
        _end = timep_t{}; 
        _start = ClockT::now(); 
    }

    void tock() { _end = ClockT::now(); }

    template <class T = DT> 
    auto duration() const { 
        gsl_Expects(_end != timep_t{} && "toc before reporting"); 
        return std::chrono::duration_cast<T>(_end - _start); 
    }
};

Comme Howard Hinnant a souligné, nous utilisons une durée pour rester dans la chrono et effectuer des opérations comme le calcul de la moyenne ou des comparaisons (par exemple, ici, cela signifie utiliser std::chrono::milliseconds ). Lorsque nous nous contentons de faire IO, nous utilisons la fonction count() ou des ticks d'une durée (par exemple ici nombre de millisecondes).

2 - Instrumentation

Tout appelable (fonction, objet fonction, lambda, etc.) peut être instrumenté pour l'analyse comparative. Disons que vous avez une fonction F invocable avec des arguments arg1,arg2 cette technique aboutit à :

cout << "F runtime=" << measure<>::duration(F, arg1, arg2).count() << "ms";

<strong>Demo</strong>

measure est défini comme suit :

template <class TimeT  = std::chrono::milliseconds
          class ClockT = std::chrono::steady_clock>
struct measure
{
    template<class F, class ...Args>
    static auto duration(F&& func, Args&&... args)
    {
        auto start = ClockT::now();
        std::invoke(std::forward<F>(func), std::forward<Args>(args)...);
        return std::chrono::duration_cast<TimeT>(ClockT::now()-start);
    }
};

Comme mentionné dans (1), l'utilisation de la durée w/o .count() est plus utile pour les clients qui veulent post-traiter un ensemble de durées avant l'E/S, par exemple la moyenne :

auto avg = (measure<>::duration(func) + measure<>::duration(func)) / 2;
std::cout << "Average run time " << avg.count() << " ms\n";

+ Ce site est la raison pour laquelle l'appel de fonction transféré.

+Le code complet peut être trouvé aquí

+Ma tentative de construire un cadre de référence basé sur le chrono est enregistré aquí

+Vieux Démonstration

2 votes

Joli ; j'ai quelque chose de similaire dans mon code, mais j'utilise une interface différente de la classe : J'ai une classe ( code_timer ) qui prend l'heure de début ( std::chrono::system_clock::now(); ) dans le constructeur, une méthode code_timer::ellapsed qui mesure la différence entre une nouvelle now() et celui du constructeur, ainsi qu'une fonction code_timer::reset qui réinitialise l'heure de départ à un nouveau now() résultat. Pour mesurer l'exécution d'un foncteur dans mon code, j'utilise une fonction libre, hors de la classe. Cela permet de mesurer le temps depuis la construction d'un objet, jusqu'à la fin d'un appel asynchrone.

0 votes

@utnapistim Thnx, j'ai demandé une revue sur ce code, vous pouvez la consulter. aquí . Si vous avez le temps, vous pourriez également développer un peu plus votre conception, elle semble excellente.

0 votes

Attention à l'optimisation du compilateur ! J'ai essayé quelque chose comme ça avant et le compilateur a optimisé l'appel à func car elle n'avait pas d'effets secondaires et la valeur de retour n'était pas utilisée.

285voto

#include <ctime>

void f() {
  using namespace std;
  clock_t begin = clock();

  code_to_time();

  clock_t end = clock();
  double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
}

En time() n'est précise qu'à une seconde près, mais il existe CLOCKS_PER_SEC "horloges" en une seconde. Il s'agit d'une mesure facile et portable, même si elle est trop simplifiée.

59voto

AKN Points 703

D'après votre question, il semble que vous souhaitiez connaître le temps écoulé après l'exécution d'un morceau de code. Je suppose que vous seriez satisfait de voir les résultats en secondes. Si c'est le cas, essayez d'utiliser difftime() comme indiqué ci-dessous. J'espère que cela résoudra votre problème.

#include <time.h>
#include <stdio.h>

time_t start,end;
time (&start);
.
.
.
<your code>
.
.
.
time (&end);
double dif = difftime (end,start);
printf ("Elasped time is %.2lf seconds.", dif );

4 votes

Cela me donne toujours des secondes entières. Est-ce que c'est censé se produire ?

14 votes

Time ne renverra toujours que des secondes, il ne peut donc pas être utilisé pour des mesures à la seconde près.

31voto

RvdK Points 10793

Windows uniquement : (Le tag Linux a été ajouté après que j'ai posté cette réponse)

Vous pouvez utiliser GetTickCount() pour obtenir le nombre de millisecondes qui se sont écoulées depuis le démarrage du système.

long int before = GetTickCount();

// Perform time-consuming operation

long int after = GetTickCount();

7 votes

Je l'utilise sous linux. Je ne peux donc pas utiliser la fonction GetTickCount().

1 votes

Déjà oublié ;) Merci de mettre à jour le tag de votre post

0 votes

Il fonctionne et donne le temps réel, pas le temps CPU. Je l'ai testé en plaçant SleepEx(5000,0) au lieu de //Préparer l'opération qui prend du temps et la différence de after y before était de presque 5 secondes.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X