time counter c++




Mide fácilmente el tiempo transcurrido (15)

Estoy tratando de usar el time() para medir varios puntos de mi programa.

Lo que no entiendo es por qué los valores del antes y el después son los mismos. Entiendo que esta no es la mejor manera de perfilar mi programa, solo quiero ver cuánto tiempo toma algo.

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

doSomthing();
doSomthingLong();

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

Yo he tratado:

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);

¿Cómo leo un resultado de **time taken = 0 26339 ? ¿Eso significa 26,339 nanosegundos = 26.3 ms?

¿Qué pasa con **time taken = 4 45025 , significa eso 4 segundos y 25 ms?


C ++ std :: chrono tiene un claro beneficio de ser multiplataforma. Sin embargo, también introduce una sobrecarga significativa en comparación con POSIX clock_gettime (). En mi caja de Linux, todos los sabores de std::chrono::xxx_clock::now() funcionan aproximadamente de la misma manera:

std::chrono::system_clock::now()
std::chrono::steady_clock::now()
std::chrono::high_resolution_clock::now()

Aunque POSIX clock_gettime(CLOCK_MONOTONIC, &time) debería ser el mismo que steady_clock::now() pero es más de 3 veces más rápido!

Aquí está mi prueba, para la integridad.

#include <stdio.h>
#include <chrono>
#include <ctime>

void print_timediff(const char* prefix, const struct timespec& start, const 
struct timespec& end)
{
    double milliseconds = (end.tv_nsec - start.tv_nsec) / 1e6 + (end.tv_sec - start.tv_sec) * 1e3;
    printf("%s: %lf milliseconds\n", prefix, milliseconds);
}

int main()
{
    int i, n = 1000000;
    struct timespec start, end;

    // Test stopwatch
    clock_gettime(CLOCK_MONOTONIC, &start);
    for (i = 0; i < n; ++i) {
        struct timespec dummy;
        clock_gettime(CLOCK_MONOTONIC, &dummy);
    }
    clock_gettime(CLOCK_MONOTONIC, &end);
    print_timediff("clock_gettime", start, end);

    // Test chrono system_clock
    clock_gettime(CLOCK_MONOTONIC, &start);
    for (i = 0; i < n; ++i)
        auto dummy = std::chrono::system_clock::now();
    clock_gettime(CLOCK_MONOTONIC, &end);
    print_timediff("chrono::system_clock::now", start, end);

    // Test chrono steady_clock
    clock_gettime(CLOCK_MONOTONIC, &start);
    for (i = 0; i < n; ++i)
        auto dummy = std::chrono::steady_clock::now();
    clock_gettime(CLOCK_MONOTONIC, &end);
    print_timediff("chrono::steady_clock::now", start, end);

    // Test chrono high_resolution_clock
    clock_gettime(CLOCK_MONOTONIC, &start);
    for (i = 0; i < n; ++i)
        auto dummy = std::chrono::high_resolution_clock::now();
    clock_gettime(CLOCK_MONOTONIC, &end);
    print_timediff("chrono::high_resolution_clock::now", start, end);

    return 0;
}

Y esta es la salida que obtengo cuando se compila con gcc7.2 -O3:

clock_gettime: 24.484926 milliseconds
chrono::system_clock::now: 85.142108 milliseconds
chrono::steady_clock::now: 87.295347 milliseconds
chrono::high_resolution_clock::now: 84.437838 milliseconds

Como otros ya han señalado, la función time () en la biblioteca estándar de C no tiene una resolución mejor que un segundo. La única función C completamente portátil que puede proporcionar una mejor resolución parece ser clock (), pero que mide el tiempo del procesador en lugar del tiempo de reloj de pared. Si uno se contenta con limitarse a las plataformas POSIX (por ejemplo, Linux), entonces la función clock_gettime () es una buena opción.

Desde C ++ 11, existen muchas mejores facilidades de temporización disponibles que ofrecen una mejor resolución en una forma que debería ser muy portátil entre diferentes compiladores y sistemas operativos. De manera similar, la biblioteca boost :: datetime proporciona buenas clases de tiempo de alta resolución que deberían ser altamente portátiles.

Un desafío en el uso de cualquiera de estas facilidades es el tiempo de retraso introducido al consultar el reloj del sistema. Al experimentar con clock_gettime (), boost::datetime y std :: chrono, este retraso puede ser fácilmente una cuestión de microsegundos. Por lo tanto, al medir la duración de cualquier parte de su código, debe permitir que exista un error de medición de alrededor de este tamaño, o intentar corregir ese error cero de alguna manera. Idealmente, es posible que desee recopilar varias mediciones del tiempo tomado por su función y calcular el promedio, o el tiempo máximo / mínimo tomado en varias ejecuciones.

Para ayudar con todos estos problemas de portabilidad y recopilación de estadísticas, he estado desarrollando la biblioteca cxx-rtimers disponible en Github que intenta proporcionar una API simple para bloques de tiempo de código C ++, calcular errores cero e informar estadísticas de múltiples temporizadores integrados en su codigo Si tiene un compilador de C ++ 11, simplemente #include <rtimers/cxx11.hpp> , y use algo como:

void expensiveFunction() {
    static rtimers::cxx11::DefaultTimer timer("expensiveFunc");
    auto scopedStartStop = timer.scopedStart();
    // Do something costly...
}

Al salir del programa, obtendrás un resumen de las estadísticas de tiempo escritas en std :: cerr como:

Timer(expensiveFunc): <t> = 6.65289us, std = 3.91685us, 3.842us <= t <= 63.257us (n=731)

que muestra el tiempo medio, su desviación estándar, los límites superior e inferior y el número de veces que se llamó a esta función.

Si desea usar funciones de tiempo específicas de Linux, puede #include <rtimers/posix.hpp> , o si tiene las bibliotecas Boost pero un compilador de C ++ más antiguo, puede #include <rtimers/boost.hpp> . También hay versiones de estas clases de temporizador que pueden recopilar información estadística de tiempo a través de múltiples hilos. También hay métodos que le permiten estimar el error cero asociado con dos consultas inmediatamente consecutivas del reloj del sistema.


En Linux, clock_gettime () es una de las buenas opciones. Debe enlazar la biblioteca en tiempo real (-lrt).

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

#define BILLION  1000000000L;

int main( int argc, char **argv )
  {
    struct timespec start, stop;
    double accum;

    if( clock_gettime( CLOCK_REALTIME, &start) == -1 ) {
      perror( "clock gettime" );
      exit( EXIT_FAILURE );
    }

    system( argv[1] );

    if( clock_gettime( CLOCK_REALTIME, &stop) == -1 ) {
      perror( "clock gettime" );
      exit( EXIT_FAILURE );
    }

    accum = ( stop.tv_sec - start.tv_sec )
          + ( stop.tv_nsec - start.tv_nsec )
            / BILLION;
    printf( "%lf\n", accum );
    return( EXIT_SUCCESS );
  }

En respuesta a las tres preguntas específicas de OP .

"Lo que no entiendo es por qué los valores del antes y el después son los mismos? "

La primera pregunta y el código de muestra muestran que el time() tiene una resolución de 1 segundo, por lo que la respuesta debe ser que las dos funciones se ejecutan en menos de 1 segundo. Pero ocasionalmente informará (aparentemente de manera ilógica) 1 segundo si las dos marcas del temporizador se ubican a horcajadas en un límite de un segundo.

El siguiente ejemplo usa gettimeofday() que llena esta estructura

struct timeval {
    time_t      tv_sec;     /* seconds */
    suseconds_t tv_usec;    /* microseconds */
};

y la segunda pregunta pregunta: "¿Cómo leo un resultado de **time taken = 0 26339 ? ¿ **time taken = 0 26339 significa 26,339 nanosegundos = 26.3 mseg?"

Mi segunda respuesta es que el tiempo empleado es de 0 segundos y 26339 microsegundos, es decir, 0.026339 segundos, lo que confirma el primer ejemplo de ejecución en menos de 1 segundo.

La tercera pregunta pregunta: "¿Qué pasa con el **time taken = 4 45025 ¿Significa eso 4 segundos y 25 ms?"

Mi tercera respuesta es que el tiempo tomado es de 4 segundos y 45025 microsegundos, es decir, 4.045025 segundos, lo que muestra que OP ha alterado las tareas realizadas por las dos funciones que previamente cronometró.


La función de tiempo (NULL) devolverá el número de segundos transcurridos desde el 01/01/1970 a las 00:00. Y porque, esa función se llama en un momento diferente en su programa, siempre será diferente el tiempo en C ++


La llamada a la función time(NULL) devolverá el número de segundos transcurridos desde epoc: 1 de enero de 1970. Tal vez lo que quieres hacer es tomar la diferencia entre dos marcas de tiempo:

size_t start = time(NULL);
doSomthing();
doSomthingLong();

printf ("**MyProgram::time elapsed= %lds\n", time(NULL) - start);

Los valores impresos por su segundo programa son segundos y microsegundos.

0 26339 = 0.026'339 s =   26339 µs
4 45025 = 4.045'025 s = 4045025 µs

Por lo que se ve, tv_sec almacena los segundos transcurridos, mientras que tv_usec almacena los microsegundos transcurridos por separado. Y no son las conversiones de los demás. Por lo tanto, deben cambiarse a la unidad adecuada y agregarse para obtener el tiempo total transcurrido.

struct timeval startTV, endTV;

gettimeofday(&startTV, NULL); 

doSomething();
doSomethingLong();

gettimeofday(&endTV, NULL); 

printf("**time taken in microseconds = %ld\n",
    (endTV.tv_sec * 1e6 + endTV.tv_usec - (startTV.tv_sec * 1e6 + startTV.tv_usec))
    );

Puede utilizar la biblioteca SFML , que es una biblioteca multimedia simple y rápida. Incluye muchas clases útiles y bien definidas como Reloj, Socket, Sonido, Gráficos, etc. Es muy fácil de usar y muy recomendable.

Este es un ejemplo para esta pregunta.

sf::Clock clock;
...
Time time1 = clock.getElapsedTime();
...
Time time2 = clock.restart();

Son los mismos porque su función doSomething ocurre más rápido que la granularidad del temporizador. Tratar:

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

for(i = 0; i < 1000; ++i) {
    doSomthing();
    doSomthingLong();
}

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

time(NULL) devuelve el número de segundos transcurridos desde el 01/01/1970 a las 00:00 ( la época ). Entonces, la diferencia entre los dos valores es la cantidad de segundos que tomó el procesamiento.

int t0 = time(NULL);
doSomthing();
doSomthingLong();
int t1 = time(NULL);

printf ("time = %d secs\n", t1 - t0);

Puede obtener mejores resultados con getttimeofday() , que devuelve la hora actual en segundos, como lo hace time() y también en microsegundos.


Sólo Windows: (la etiqueta de Linux se agregó después de que publiqué esta respuesta)

Puede usar GetTickCount() para obtener la cantidad de milisegundos que han transcurrido desde que se inició el sistema.

long int before = GetTickCount();

// Perform time-consuming operation

long int after = GetTickCount();

#include <ctime>
#include <cstdio>
#include <iostream>
#include <chrono>
#include <sys/time.h>
using namespace std;
using namespace std::chrono;

void f1()
{
  high_resolution_clock::time_point t1 = high_resolution_clock::now();
  high_resolution_clock::time_point t2 = high_resolution_clock::now();
  double dif = duration_cast<nanoseconds>( t2 - t1 ).count();
  printf ("Elasped time is %lf nanoseconds.\n", dif );
}

void f2()
{
  timespec ts1,ts2;
  clock_gettime(CLOCK_REALTIME, &ts1);
  clock_gettime(CLOCK_REALTIME, &ts2);
  double dif = double( ts2.tv_nsec - ts1.tv_nsec );
  printf ("Elasped time is %lf nanoseconds.\n", dif );
}

void f3()
{
  struct timeval t1,t0;
  gettimeofday(&t0, 0);
  gettimeofday(&t1, 0);
  double dif = double( (t1.tv_usec-t0.tv_usec)*1000);
  printf ("Elasped time is %lf nanoseconds.\n", dif );
}
void f4()
{
  high_resolution_clock::time_point t1 , t2;
  double diff = 0;
  t1 = high_resolution_clock::now() ;
  for(int i = 1; i <= 10 ; i++)
  {
    t2 = high_resolution_clock::now() ;
    diff+= duration_cast<nanoseconds>( t2 - t1 ).count();
    t1 = t2;
  }
  printf ("high_resolution_clock:: Elasped time is %lf nanoseconds.\n", diff/10 );
}

void f5()
{
  timespec ts1,ts2;
  double diff = 0;
  clock_gettime(CLOCK_REALTIME, &ts1);
  for(int i = 1; i <= 10 ; i++)
  {
    clock_gettime(CLOCK_REALTIME, &ts2);
    diff+= double( ts2.tv_nsec - ts1.tv_nsec );
    ts1 = ts2;
  }
  printf ("clock_gettime:: Elasped time is %lf nanoseconds.\n", diff/10 );
}

void f6()
{
  struct timeval t1,t2;
  double diff = 0;
  gettimeofday(&t1, 0);
  for(int i = 1; i <= 10 ; i++)
  {
    gettimeofday(&t2, 0);
    diff+= double( (t2.tv_usec-t1.tv_usec)*1000);
    t1 = t2;
  }
  printf ("gettimeofday:: Elasped time is %lf nanoseconds.\n", diff/10 );
}

int main()
{
  //  f1();
  //  f2();
  //  f3();
  f6();
  f4();
  f5();
  return 0;
}

#include<time.h> // for clock
#include<math.h> // for fmod
#include<cstdlib> //for system
#include <stdio.h> //for delay

using namespace std;

int main()
{


   clock_t t1,t2;

   t1=clock(); // first time capture

   // Now your time spanning loop or code goes here
   // i am first trying to display time elapsed every time loop runs

   int ddays=0; // d prefix is just to say that this variable will be used for display
   int dhh=0;
   int dmm=0;
   int dss=0;

   int loopcount = 1000 ; // just for demo your loop will be different of course

   for(float count=1;count<loopcount;count++)
   {

     t2=clock(); // we get the time now

     float difference= (((float)t2)-((float)t1)); // gives the time elapsed since t1 in milliseconds

    // now get the time elapsed in seconds

    float seconds = difference/1000; // float value of seconds
    if (seconds<(60*60*24)) // a day is not over
    {
        dss = fmod(seconds,60); // the remainder is seconds to be displayed
        float minutes= seconds/60;  // the total minutes in float
        dmm= fmod(minutes,60);  // the remainder are minutes to be displayed
        float hours= minutes/60; // the total hours in float
        dhh= hours;  // the hours to be displayed
        ddays=0;
    }
    else // we have reached the counting of days
    {
        float days = seconds/(24*60*60);
        ddays = (int)(days);
        float minutes= seconds/60;  // the total minutes in float
        dmm= fmod(minutes,60);  // the rmainder are minutes to be displayed
        float hours= minutes/60; // the total hours in float
        dhh= fmod (hours,24);  // the hours to be displayed

    }

    cout<<"Count Is : "<<count<<"Time Elapsed : "<<ddays<<" Days "<<dhh<<" hrs "<<dmm<<" mins "<<dss<<" secs";


    // the actual working code here,I have just put a delay function
    delay(1000);
    system("cls");

 } // end for loop

}// end of main 

struct profiler
{
    std::string name;
    std::chrono::high_resolution_clock::time_point p;
    profiler(std::string const &n) :
        name(n), p(std::chrono::high_resolution_clock::now()) { }
    ~profiler()
    {
        using dura = std::chrono::duration<double>;
        auto d = std::chrono::high_resolution_clock::now() - p;
        std::cout << name << ": "
            << std::chrono::duration_cast<dura>(d).count()
            << std::endl;
    }
};

#define PROFILE_BLOCK(pbn) profiler _pfinstance(pbn)

El uso es a continuación ::

{
    PROFILE_BLOCK("Some time");
    // your code or function
}

Esto es similar a RAII en alcance

NOTA: esto no es mío, pero pensé que era relevante aquí







measurement